// ==UserScript==
// @name 齐大教务助手
// @namespace https://greasyfork.org/users/737539
// @version 2.3.4
// @description 集成抢课功能与教学评估功能,一体化教务助手
// @author 忘忧
// @icon https://xyh.qqhru.edu.cn/favicon.ico
// @license MIT
// @match http://111.43.36.164/student/teachingEvaluation/evaluation/index
// @match http://111.43.36.164/student/courseSelect/courseSelect/index
// @match http://111.43.36.164/student/teachingEvaluation/teachingEvaluation/evaluationPage
// @match http://111.43.36.164/student/teachingEvaluation/teachingEvaluation/index
// @match http://172.20.139.153:7700/student/teachingEvaluation/teachingEvaluation/evaluationPage
// @match http://172.20.139.153:7700/student/teachingEvaluation/teachingEvaluation/index
// @match https://172-20-139-153-7700.webvpn.qqhru.edu.cn/student/teachingEvaluation/teachingEvaluation/evaluationPage
// @match https://172-20-139-153-7700.webvpn.qqhru.edu.cn/student/teachingEvaluation/teachingEvaluation/index
// @match https://172-20-139-153-7700.webvpn.qqhru.edu.cn/student/teachingEvaluation/evaluation/index
// @match http://172.20.139.153:7700/student/teachingEvaluation/evaluation/index
// @match http://172.20.139.153:7700/student/courseSelect/courseSelect/index
// @grant none
// ==/UserScript==
(function () {
'use strict';
/**
* 齐大教务助手主模块
* 模块化结构,将不同功能划分为独立模块
*/
const EducationHelper = {
// 系统配置
Config: {
// 全局状态
state: {
targetCourses: [],
matchedCourses: [],
timer: null,
autoMode: false,
autoClickEvaluationEnabled: false,
selectedOption: "A",
autoSubmitEnabled: true,
debugMode: false,
uiFollowPage: true,
},
// 页面类型
pageType: {
currentPageUrl: window.location.href,
isCoursePage: false,
isEvaluationPage: false,
isEvaluationListPage: false
},
// 时间设置
timers: {
autoClickEvaluationDelay: 10000, // 延迟10秒执行自动点击
autoSubmitDelay: 120000, // 自动提交延迟,默认2分钟
},
// 内容设置
content: {
evaluationComment: "上课有热情,积极解决学生问题,很好的老师!!", // 默认评价内容
},
// 初始化配置
init: function() {
// 检测页面类型
this.pageType.isCoursePage = this.pageType.currentPageUrl.includes('courseSelect');
this.pageType.isEvaluationPage = this.pageType.currentPageUrl.includes('teachingEvaluation/evaluationPage');
this.pageType.isEvaluationListPage = this.pageType.currentPageUrl.includes('teachingEvaluation/teachingEvaluation/index') ||
this.pageType.currentPageUrl.includes('teachingEvaluation/evaluation/index');
// 从localStorage读取持久化设置
this.loadSavedSettings();
return this;
},
// 保存设置到localStorage
saveSettings: function() {
try {
localStorage.setItem('autoMode', this.state.autoMode.toString());
localStorage.setItem('evaluationComment', this.content.evaluationComment);
localStorage.setItem('selectedOption', this.state.selectedOption);
console.log('[设置] 已保存设置到localStorage');
} catch (e) {
console.warn("[警告] 保存设置到localStorage失败:", e);
}
},
// 从localStorage加载设置
loadSavedSettings: function() {
try {
const storedAutoMode = localStorage.getItem('autoMode');
if (storedAutoMode === 'true') {
this.state.autoMode = true;
console.log('[检测] 从localStorage检测到全自动模式已启用');
}
const storedComment = localStorage.getItem('evaluationComment');
if (storedComment) {
this.content.evaluationComment = storedComment;
}
const storedOption = localStorage.getItem('selectedOption');
if (storedOption) {
this.state.selectedOption = storedOption;
}
} catch (e) {
console.warn("[警告] 读取localStorage失败:", e);
}
}
},
// 日志模块
Logger: {
// 调试日志
debug: function(message, data) {
if (EducationHelper.Config.state.debugMode) {
console.log(`[调试] ${message}`, data || '');
const debugContent = document.getElementById('debugContent');
if (debugContent) {
const logItem = document.createElement('div');
logItem.style.borderBottom = '1px dashed #eee';
logItem.style.paddingBottom = '3px';
logItem.style.marginBottom = '3px';
let logText = message;
if (data) {
if (typeof data === 'object') {
try {
logText += ` ${JSON.stringify(data)}`;
} catch (e) {
logText += ` [复杂对象]`;
}
} else {
logText += ` ${data}`;
}
}
logItem.textContent = logText;
debugContent.appendChild(logItem);
debugContent.scrollTop = debugContent.scrollHeight; // 自动滚动到底部
}
}
},
// 信息日志
info: function(message) {
console.log(`[信息] ${message}`);
},
// 操作日志
action: function(message) {
console.log(`[操作] ${message}`);
},
// 成功日志
success: function(message) {
console.log(`[成功] ${message}`);
},
// 警告日志
warn: function(message) {
console.warn(`[警告] ${message}`);
},
// 错误日志
error: function(message, error) {
if (error) {
console.error(`[错误] ${message}`, error);
} else {
console.error(`[错误] ${message}`);
}
}
},
// UI模块
UI: {
// UI元素
elements: {
container: null,
dragBar: null,
content: null,
},
// UI样式 - iOS风格设计
styles: {
// 将在初始化时添加
cssRules: `
/* iOS风格全局样式 */
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* iOS风格按钮 */
.ui-button {
background: linear-gradient(135deg, #007AFF, #0051D5);
color: white;
border: none;
padding: 12px 16px;
cursor: pointer;
width: 100%;
margin-bottom: 12px;
border-radius: 12px;
transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94);
font-weight: 600;
font-size: 16px;
letter-spacing: -0.24px;
box-shadow: 0 2px 8px rgba(0, 122, 255, 0.25);
position: relative;
overflow: hidden;
}
.ui-button::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.1), rgba(255,255,255,0));
border-radius: 12px;
pointer-events: none;
}
.ui-button:hover {
background: linear-gradient(135deg, #0051D5, #003D9F);
transform: translateY(-1px);
box-shadow: 0 4px 16px rgba(0, 122, 255, 0.35);
}
.ui-button:active {
transform: scale(0.96);
box-shadow: 0 1px 4px rgba(0, 122, 255, 0.2);
}
.ui-button:disabled {
background: #E5E5EA;
color: #8E8E93;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
/* iOS风格输入框 */
.ui-input {
width: 100%;
padding: 12px 16px;
margin-bottom: 12px;
border: 1px solid #E5E5EA;
border-radius: 12px;
box-sizing: border-box;
font-size: 16px;
background: #FFFFFF;
transition: all 0.2s ease;
-webkit-appearance: none;
}
.ui-input:focus {
outline: none;
border-color: #007AFF;
box-shadow: 0 0 0 3px rgba(0, 122, 255, 0.1);
}
/* iOS风格标签 */
.ui-label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #1C1C1E;
font-size: 15px;
letter-spacing: -0.24px;
}
/* iOS风格面板 */
.ui-panel {
border: none;
border-radius: 16px;
padding: 16px;
margin-bottom: 16px;
background: #F2F2F7;
max-height: 140px;
overflow-y: auto;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.ui-panel-title {
font-weight: 700;
margin-bottom: 8px;
color: #007AFF;
font-size: 16px;
letter-spacing: -0.32px;
}
/* iOS风格标签页 */
.ui-tabs {
display: flex;
margin-bottom: 16px;
background: #F2F2F7;
border-radius: 12px;
padding: 4px;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
}
.ui-tab {
flex: 1;
padding: 10px 16px;
cursor: pointer;
background: transparent;
border: none;
border-radius: 8px;
margin: 0;
font-weight: 500;
color: #8E8E93;
transition: all 0.2s ease;
text-align: center;
font-size: 15px;
}
.ui-tab.active {
background: #FFFFFF;
color: #007AFF;
font-weight: 600;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.ui-tab-content {
display: none;
}
.ui-tab-content.active {
display: block;
}
/* iOS风格删除按钮 */
.delete-btn {
background: #FF3B30;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
padding: 6px 12px;
font-size: 14px;
font-weight: 500;
transition: all 0.2s ease;
}
.delete-btn:hover {
background: #D70015;
transform: scale(0.95);
}
/* 课程项目 */
.course-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
border-bottom: 1px solid #E5E5EA;
font-size: 15px;
}
.course-item:last-child {
border-bottom: none;
}
/* iOS风格复选框容器 */
.ui-checkbox-container {
display: flex;
align-items: center;
margin-bottom: 16px;
padding: 12px 16px;
background: #F2F2F7;
border-radius: 12px;
}
.ui-checkbox {
margin-right: 12px;
width: 20px;
height: 20px;
accent-color: #007AFF;
}
/* 选项容器 */
.option-container {
margin-bottom: 16px;
background: #F2F2F7;
border-radius: 12px;
padding: 8px;
}
.option-row {
margin-bottom: 0;
}
.radio-label {
display: flex;
align-items: center;
cursor: pointer;
padding: 12px 16px;
border-radius: 8px;
transition: background-color 0.2s ease;
font-size: 15px;
font-weight: 500;
}
.radio-label:hover {
background: rgba(0, 122, 255, 0.1);
}
.radio-label input {
margin-right: 12px;
width: 18px;
height: 18px;
accent-color: #007AFF;
}
/* iOS风格计时器显示 */
.timer-display {
background: linear-gradient(135deg, #34C759, #30A14E);
color: white;
padding: 12px 16px;
border-radius: 12px;
text-align: center;
margin-bottom: 16px;
font-weight: 600;
font-size: 16px;
display: none;
box-shadow: 0 2px 8px rgba(52, 199, 89, 0.25);
}
`,
// 添加CSS样式到页面
addStyles: function() {
const style = document.createElement('style');
style.innerHTML = this.cssRules;
document.head.appendChild(style);
}
},
// 创建UI界面 - iOS风格
create: function() {
EducationHelper.Logger.action('正在创建iOS风格UI...');
// 添加样式
this.styles.addStyles();
// 创建主容器
this.elements.container = document.createElement('div');
this.elements.container.id = 'qqhruHelperUI';
this.elements.container.style.position = EducationHelper.Config.state.uiFollowPage ? 'fixed' : 'absolute';
this.elements.container.style.top = '20px';
this.elements.container.style.right = '20px';
this.elements.container.style.width = '320px';
this.elements.container.style.backgroundColor = '#FFFFFF';
this.elements.container.style.border = 'none';
this.elements.container.style.padding = '0';
this.elements.container.style.zIndex = '9999';
this.elements.container.style.boxShadow = '0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 8px rgba(0, 0, 0, 0.1)';
this.elements.container.style.borderRadius = '20px';
this.elements.container.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif';
this.elements.container.style.backdropFilter = 'blur(20px)';
this.elements.container.style.webkitBackdropFilter = 'blur(20px)';
this.elements.container.style.overflow = 'hidden';
// iOS风格标题和内容区域HTML
this.elements.container.innerHTML = `
`;
document.body.appendChild(this.elements.container);
// 保存元素引用
this.elements.dragBar = document.getElementById('dragBar');
this.elements.content = document.getElementById('uiContent');
// 根据页面类型生成内容
this.generateContent();
// 实现拖动功能
this.makeDraggable();
// 添加按钮事件
document.getElementById('minimizeBtn').addEventListener('click', this.toggleMinimize.bind(this));
document.getElementById('closeBtn').addEventListener('click', () => {
// iOS风格关闭动画
this.elements.container.style.transform = 'scale(0.8)';
this.elements.container.style.opacity = '0';
setTimeout(() => {
this.elements.container.style.display = 'none';
this.elements.container.style.transform = 'scale(1)';
this.elements.container.style.opacity = '1';
}, 200);
});
EducationHelper.Logger.success('iOS风格UI创建完成');
return this;
},
// 根据页面类型生成内容
generateContent: function() {
// 将在后续实现
EducationHelper.Logger.action('生成页面内容');
},
// 使UI可拖动
makeDraggable: function() {
let offsetX = 0;
let offsetY = 0;
let isDragging = false;
this.elements.dragBar.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - this.elements.container.getBoundingClientRect().left;
offsetY = e.clientY - this.elements.container.getBoundingClientRect().top;
this.elements.dragBar.style.cursor = 'grabbing';
document.body.style.userSelect = 'none';
});
document.addEventListener('mousemove', (e) => {
if (isDragging) {
let newX = e.clientX - offsetX;
let newY = e.clientY - offsetY;
// 限制UI在页面内
const maxX = window.innerWidth - this.elements.container.offsetWidth;
const maxY = window.innerHeight - this.elements.container.offsetHeight;
if (newX < 0) newX = 0;
if (newY < 0) newY = 0;
if (newX > maxX) newX = maxX;
if (newY > maxY) newY = maxY;
this.elements.container.style.left = `${newX}px`;
this.elements.container.style.top = `${newY}px`;
}
});
document.addEventListener('mouseup', () => {
isDragging = false;
this.elements.dragBar.style.cursor = 'grab';
document.body.style.userSelect = '';
});
},
// 切换最小化状态 - iOS风格动画
toggleMinimize: function() {
const content = this.elements.content;
const btn = document.getElementById('minimizeBtn');
if (content.style.display === 'none') {
// 展开动画
content.style.display = 'block';
content.style.opacity = '0';
content.style.transform = 'translateY(-10px)';
setTimeout(() => {
content.style.transition = 'all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)';
content.style.opacity = '1';
content.style.transform = 'translateY(0)';
}, 10);
btn.textContent = '−';
btn.style.transform = 'rotate(0deg)';
} else {
// 收起动画
content.style.transition = 'all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94)';
content.style.opacity = '0';
content.style.transform = 'translateY(-10px)';
setTimeout(() => {
content.style.display = 'none';
content.style.transition = '';
}, 300);
btn.textContent = '+';
btn.style.transform = 'rotate(90deg)';
}
},
// 显示状态消息 - iOS风格
showMessage: function(message, type = 'info', duration = 3000) {
const msgElement = document.createElement('div');
msgElement.style = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.8);
padding: 20px 24px;
border-radius: 16px;
z-index: 10000;
text-align: center;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.25), 0 2px 8px rgba(0, 0, 0, 0.1);
color: white;
font-weight: 600;
font-size: 16px;
letter-spacing: -0.24px;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
opacity: 0;
transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
max-width: 300px;
min-width: 200px;
`;
// 根据类型设置iOS风格颜色
switch(type) {
case 'success':
msgElement.style.background = 'rgba(52, 199, 89, 0.9)';
break;
case 'error':
msgElement.style.background = 'rgba(255, 59, 48, 0.9)';
break;
case 'warning':
msgElement.style.background = 'rgba(255, 149, 0, 0.9)';
break;
default:
msgElement.style.background = 'rgba(0, 122, 255, 0.9)';
}
msgElement.innerHTML = message;
document.body.appendChild(msgElement);
// iOS风格进入动画
setTimeout(() => {
msgElement.style.opacity = '1';
msgElement.style.transform = 'translate(-50%, -50%) scale(1)';
}, 10);
// 自动消失
if (duration > 0) {
setTimeout(() => {
if (msgElement && document.contains(msgElement)) {
// iOS风格退出动画
msgElement.style.opacity = '0';
msgElement.style.transform = 'translate(-50%, -50%) scale(0.8)';
setTimeout(() => {
if (msgElement && document.contains(msgElement)) {
msgElement.remove();
}
}, 300);
}
}, duration);
}
return msgElement;
}
},
/**
* 其他模块将在后续添加
*/
// 抢课模块
CourseGrabber: {
// 课程列表操作
courseList: {
// 添加课程
add: function(courseCode) {
if (!courseCode) return false;
const courses = courseCode.split('\n').map(code => code.trim());
courses.forEach(course => {
if (course && !EducationHelper.Config.state.targetCourses.includes(course)) {
EducationHelper.Config.state.targetCourses.push(course);
}
});
this.updateUI();
EducationHelper.Logger.success(`已添加课程: ${courses.join(', ')}`);
return true;
},
// 移除课程
remove: function(index) {
if (index >= 0 && index < EducationHelper.Config.state.targetCourses.length) {
const removedCourse = EducationHelper.Config.state.targetCourses.splice(index, 1)[0];
this.updateUI();
EducationHelper.Logger.success(`已移除课程: ${removedCourse}`);
return true;
}
return false;
},
// 更新课程列表UI - iOS风格
updateUI: function() {
const courseListDiv = document.getElementById('courseList');
if (!courseListDiv) return;
courseListDiv.innerHTML = '';
if (EducationHelper.Config.state.targetCourses.length === 0) {
courseListDiv.innerHTML = `
暂无课程,请先添加课程代码
`;
} else {
EducationHelper.Config.state.targetCourses.forEach((course, index) => {
const courseItem = document.createElement('div');
courseItem.className = 'course-item';
courseItem.style.cssText = `
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
border-bottom: 1px solid #E5E5EA;
font-size: 15px;
font-weight: 500;
`;
courseItem.innerHTML = `
${course}
`;
// 最后一个项目不显示底部边框
if (index === EducationHelper.Config.state.targetCourses.length - 1) {
courseItem.style.borderBottom = 'none';
}
courseListDiv.appendChild(courseItem);
});
// 添加删除按钮事件
courseListDiv.querySelectorAll('.delete-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const idx = parseInt(e.target.getAttribute('data-index'));
this.remove(idx);
});
// 添加悬停效果
btn.addEventListener('mouseenter', function() {
this.style.background = '#D70015';
this.style.transform = 'scale(0.95)';
});
btn.addEventListener('mouseleave', function() {
this.style.background = '#FF3B30';
this.style.transform = 'scale(1)';
});
});
}
}
},
// 匹配成功课程操作
matchedCourses: {
// 添加匹配成功的课程
add: function(courseCode) {
if (courseCode && !EducationHelper.Config.state.matchedCourses.includes(courseCode)) {
EducationHelper.Config.state.matchedCourses.push(courseCode);
this.updateUI();
EducationHelper.Logger.success(`已添加匹配成功课程: ${courseCode}`);
return true;
}
return false;
},
// 更新匹配成功课程UI - iOS风格
updateUI: function() {
const matchedCoursesDiv = document.getElementById('matchedCourses');
if (!matchedCoursesDiv) return;
matchedCoursesDiv.innerHTML = '';
if (EducationHelper.Config.state.matchedCourses.length === 0) {
matchedCoursesDiv.innerHTML = `
暂无匹配成功的课程
`;
} else {
EducationHelper.Config.state.matchedCourses.forEach((course, index) => {
const courseItem = document.createElement('div');
courseItem.className = 'course-item';
courseItem.style.cssText = `
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 0;
border-bottom: 1px solid #E5E5EA;
font-size: 15px;
font-weight: 500;
`;
courseItem.innerHTML = `
✅
${course}
`;
// 最后一个项目不显示底部边框
if (index === EducationHelper.Config.state.matchedCourses.length - 1) {
courseItem.style.borderBottom = 'none';
}
matchedCoursesDiv.appendChild(courseItem);
});
}
}
},
// 抢课过程控制
control: {
// 启动抢课
start: function() {
if (EducationHelper.Config.state.targetCourses.length === 0) {
EducationHelper.UI.showMessage('请先添加课程', 'error');
return false;
}
// 设置按钮状态
document.getElementById('startScript').disabled = true;
document.getElementById('stopScript').disabled = false;
// 启动定时器
EducationHelper.Config.state.timer = setInterval(this.checkAndSelectCourses.bind(this), 1000);
EducationHelper.Logger.action('抢课脚本已启动');
return true;
},
// 停止抢课
stop: function() {
if (EducationHelper.Config.state.timer) {
clearInterval(EducationHelper.Config.state.timer);
EducationHelper.Config.state.timer = null;
// 设置按钮状态
document.getElementById('startScript').disabled = false;
document.getElementById('stopScript').disabled = true;
EducationHelper.Logger.action('抢课脚本已停止');
return true;
}
return false;
},
// 检查并选择课程
checkAndSelectCourses: function() {
EducationHelper.Logger.action('开始检查课程...');
const iframeDoc = document.querySelector('#ifra')?.contentDocument;
if (!iframeDoc) {
EducationHelper.Logger.error('无法获取 iframe 文档');
return;
}
if (EducationHelper.Config.state.targetCourses.length === 0) {
EducationHelper.Logger.action('所有课程已处理,尝试提交...');
this.clickSubmitButton();
this.stop();
return;
}
const courseCode = EducationHelper.Config.state.targetCourses[0];
const rows = iframeDoc.querySelectorAll('tr');
EducationHelper.Logger.debug(`正在匹配课程代码: ${courseCode},总共找到 ${rows.length} 行课程数据`);
let matched = false;
rows.forEach((row) => {
const courseCells = row.querySelectorAll('td[rowspan]');
courseCells.forEach((courseCell) => {
const cellText = courseCell.textContent.trim();
const cellNumber = cellText.match(/\d+/g)?.join('') || '';
EducationHelper.Logger.debug(`检查单元格内容: ${cellText}, 提取的数字: ${cellNumber}`);
if (cellNumber === courseCode) {
matched = true;
EducationHelper.Logger.success(`匹配成功 - 课程代码: ${courseCode}, 单元格内容: ${cellText}`);
const checkbox = row.querySelector(`input[type="checkbox"]`);
if (checkbox && !checkbox.checked) {
checkbox.click();
EducationHelper.Logger.success(`已勾选课程: ${courseCode}`);
}
}
});
});
if (matched) {
EducationHelper.Logger.action(`已处理课程: ${courseCode}`);
EducationHelper.CourseGrabber.matchedCourses.add(courseCode);
EducationHelper.Config.state.targetCourses.shift();
} else {
EducationHelper.Logger.warn(`未匹配到课程代码: ${courseCode}`);
}
},
// 点击提交按钮
clickSubmitButton: function() {
const button = document.querySelector('#submitButton');
if (button) {
EducationHelper.Logger.action('找到提交按钮,正在尝试提交...');
const event = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
button.dispatchEvent(event);
EducationHelper.Logger.success('已提交选课请求');
return true;
} else {
EducationHelper.Logger.warn('未找到提交按钮,请检查页面结构');
return false;
}
}
},
// UI内容生成 - iOS风格
generateUI: function() {
return `
`;
},
// 注册事件监听
bindEvents: function() {
document.getElementById('addCourses').addEventListener('click', () => {
const courseCodesInput = document.getElementById('courseCode').value.trim();
if (this.courseList.add(courseCodesInput)) {
document.getElementById('courseCode').value = '';
}
});
document.getElementById('startScript').addEventListener('click', () => {
this.control.start();
});
document.getElementById('stopScript').addEventListener('click', () => {
this.control.stop();
});
},
// 初始化抢课模块
init: function() {
// 只在课程选择页面初始化
if (!EducationHelper.Config.pageType.isCoursePage) return;
EducationHelper.Logger.action('初始化抢课模块...');
// 其他初始化操作
return this;
}
},
// 评估模块 - 处理单个评估页面
Evaluator: {
// 选项选择功能
optionSelector: {
// 根据所选字母选择选项
selectByLetter: function(letter) {
EducationHelper.Logger.action(`正在选择${letter}选项...`);
// 更新配置中的选择
EducationHelper.Config.state.selectedOption = letter;
try {
// 使用jQuery选择选项
$(".ace").each(function() {
var self = $(this);
var text = $(this).next().next().html();
if (text && text.indexOf(`(${letter})`) !== -1) {
self.click();
}
});
EducationHelper.Logger.success(`已全选${letter}选项`);
return true;
} catch (error) {
EducationHelper.Logger.error(`选择${letter}选项时出错`, error);
return false;
}
}
},
// 评价内容填写
contentFiller: {
// 填写评价内容
fillContent: function(content) {
content = content || EducationHelper.Config.content.evaluationComment;
EducationHelper.Logger.action('正在填写评价内容...');
try {
// 尝试多种选择器找到文本区域
let filled = false;
// 1. 通过name属性查找
const mainTextarea = document.querySelector('textarea[name="zgpj"]');
if (mainTextarea) {
mainTextarea.value = content;
// 触发change事件
const event = new Event('input', { bubbles: true });
mainTextarea.dispatchEvent(event);
EducationHelper.Logger.success("已通过name='zgpj'找到并填写主观评价文本框");
filled = true;
}
// 2. 查找所有文本区域
if (!filled) {
const textareas = document.querySelectorAll('textarea.form-control');
if (textareas.length > 0) {
for (const textarea of textareas) {
textarea.value = content;
const event = new Event('input', { bubbles: true });
textarea.dispatchEvent(event);
}
EducationHelper.Logger.success("已填写所有文本框");
filled = true;
}
}
// 3. 使用jQuery选择器
if (!filled) {
const jqTextarea = $("#page-content-template > div > div > div.widget-content > form > div > table > tbody > tr:nth-child(25) > td > div > textarea");
if (jqTextarea.length > 0) {
jqTextarea.val(content);
EducationHelper.Logger.success("已使用jQuery选择器填写评价内容");
filled = true;
}
}
// 4. 最后尝试任何文本区域
if (!filled) {
const allTextareas = document.querySelectorAll('textarea');
if (allTextareas.length > 0) {
for (const textarea of allTextareas) {
textarea.value = content;
const event = new Event('input', { bubbles: true });
textarea.dispatchEvent(event);
}
EducationHelper.Logger.success("已填写所有找到的文本区域");
filled = true;
}
}
return filled;
} catch (error) {
EducationHelper.Logger.error("填写评价内容时出错", error);
return false;
}
}
},
// 评价提交处理
submitter: {
// 倒计时组件
countdown: {
timer: null,
seconds: 0,
// 开始倒计时
start: function(duration, onComplete) {
// 停止现有倒计时
this.stop();
// 设置初始秒数
this.seconds = duration || EducationHelper.Config.timers.autoSubmitDelay / 1000;
// 确保倒计时显示元素存在且可见
this.ensureDisplayExists();
// 更新显示
this.updateDisplay();
// 开始倒计时
this.timer = setInterval(() => {
this.seconds--;
this.updateDisplay();
if (this.seconds <= 0) {
this.stop();
if (typeof onComplete === 'function') {
onComplete();
}
}
}, 1000);
return this;
},
// 停止倒计时
stop: function() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
return this;
},
// 确保倒计时显示元素存在
ensureDisplayExists: function() {
// 检查是否已存在倒计时显示
let timerDisplay = document.getElementById('timerDisplay');
// 如果不存在,创建一个新的
if (!timerDisplay) {
EducationHelper.Logger.action('创建倒计时显示元素');
timerDisplay = document.createElement('div');
timerDisplay.id = 'timerDisplay';
timerDisplay.className = 'timer-display';
// 添加到UI容器中
const uiContent = document.getElementById('uiContent');
if (uiContent) {
// 添加到UI内容区的合适位置
const buttons = uiContent.querySelector('div[style*="display: flex"]');
if (buttons) {
uiContent.insertBefore(timerDisplay, buttons);
} else {
// 如果找不到按钮区域,添加到内容区最后
uiContent.appendChild(timerDisplay);
}
} else {
// 如果找不到UI容器,添加到body
document.body.appendChild(timerDisplay);
}
}
// 确保样式正确
timerDisplay.style.display = 'block';
timerDisplay.style.backgroundColor = '#e3f2fd';
timerDisplay.style.border = '1px solid #1976d2';
timerDisplay.style.padding = '10px';
timerDisplay.style.borderRadius = '4px';
timerDisplay.style.marginBottom = '10px';
timerDisplay.style.fontWeight = 'bold';
timerDisplay.style.fontSize = '16px';
timerDisplay.style.textAlign = 'center';
timerDisplay.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
// 设置初始内容
if (!timerDisplay.innerHTML || !timerDisplay.innerHTML.includes('timerValue')) {
timerDisplay.innerHTML = '等待提交: 120 秒';
}
// 如果是自动模式,使用不同的样式
if (EducationHelper.Config.state.autoMode) {
timerDisplay.style.backgroundColor = '#e8f5e9';
timerDisplay.style.border = '1px solid #4caf50';
timerDisplay.innerHTML = '⏱️ 自动提交倒计时: 120 秒';
}
return timerDisplay;
},
// 更新倒计时显示
updateDisplay: function() {
const timerElement = document.getElementById('timerValue');
if (timerElement) {
timerElement.textContent = this.seconds;
}
return this;
}
},
// 查找并点击提交按钮
findAndClickSubmitButton: function(showMessage = true) {
EducationHelper.Logger.action('查找提交按钮...');
// 显示状态消息
let statusMsg = null;
if (showMessage) {
statusMsg = EducationHelper.UI.showMessage('正在提交评价...
', 'info', 0); // 0表示不自动消失
}
setTimeout(() => {
// 收集所有可能的按钮,生成一个优先级列表
const possibleButtons = [];
// 查找带有"提交"文本的所有按钮
const allButtons = document.querySelectorAll('button, input[type="submit"], input[type="button"]');
EducationHelper.Logger.debug(`找到 ${allButtons.length} 个按钮元素`);
allButtons.forEach(btn => {
const btnText = btn.textContent || btn.value || '';
EducationHelper.Logger.debug(`检查按钮: "${btnText}", HTML: ${btn.outerHTML}`);
// 按钮匹配度评分
let score = 0;
// 文本包含"提交"
if (btnText.includes('提交')) {
score += 10;
}
// 底部按钮优先
const rect = btn.getBoundingClientRect();
if (rect.top > window.innerHeight / 2) {
score += 5;
}
// 样式匹配度
if (btn.className.includes('btn-danger') ||
btn.className.includes('btn-primary') ||
btn.className.includes('layui-btn')) {
score += 3;
}
// 有红色或蓝色背景
const style = window.getComputedStyle(btn);
const bgColor = style.backgroundColor;
if (bgColor.includes('rgb(') &&
(bgColor.includes('255') || bgColor.includes('0, 0, 255'))) {
score += 2;
}
// 如果得分大于0,添加到可能按钮列表
if (score > 0) {
possibleButtons.push({button: btn, score: score});
}
});
// 按得分排序
possibleButtons.sort((a, b) => b.score - a.score);
// 选择得分最高的按钮
let submitButton = null;
if (possibleButtons.length > 0) {
submitButton = possibleButtons[0].button;
EducationHelper.Logger.success(`找到提交按钮, 得分: ${possibleButtons[0].score}`);
}
// 如果没找到按钮,尝试其他方法
if (!submitButton) {
// 尝试特定ID或名称
submitButton = document.querySelector('#submit, #btnSubmit, .submit-btn, [name="submit"]');
if (!submitButton) {
// 尝试表单提交按钮
const forms = document.querySelectorAll('form');
forms.forEach(form => {
const submitBtn = form.querySelector('[type="submit"]');
if (submitBtn) {
submitButton = submitBtn;
}
});
}
}
// 点击提交按钮
if (submitButton) {
// 更新状态提示
if (statusMsg) {
statusMsg.innerHTML = '找到提交按钮,正在点击...
';
}
EducationHelper.Logger.action("找到提交按钮,点击提交");
// 确保按钮可见
submitButton.scrollIntoView({behavior: 'smooth', block: 'center'});
// 加上小延迟,确保滚动完成后再点击
setTimeout(() => {
// 点击按钮
submitButton.click();
// 处理确认对话框
this.handleConfirmDialog(statusMsg);
}, 500);
return true;
} else {
EducationHelper.Logger.warn("未找到提交按钮");
if (statusMsg) {
statusMsg.innerHTML = '未找到提交按钮,尝试其他方法...
';
}
// 尝试直接提交表单
const mainForm = document.querySelector('form');
if (mainForm) {
EducationHelper.Logger.action("尝试直接提交表单");
try {
mainForm.submit();
EducationHelper.Logger.success("已调用表单的submit()方法");
if (statusMsg) {
statusMsg.innerHTML = '已尝试提交表单,请检查是否成功
';
// 2秒后移除状态提示
setTimeout(() => {
if (statusMsg && document.contains(statusMsg)) {
statusMsg.remove();
}
}, 2000);
}
return true;
} catch (e) {
EducationHelper.Logger.error("尝试提交表单失败", e);
if (statusMsg) {
statusMsg.innerHTML = '自动提交失败,请手动点击页面中的"提交"按钮
';
// 5秒后移除提示
setTimeout(() => {
if (statusMsg && document.contains(statusMsg)) {
statusMsg.remove();
}
}, 5000);
}
return false;
}
} else {
// 提示用户手动提交
if (statusMsg) {
statusMsg.innerHTML = '未找到提交按钮,请手动点击页面中的"提交"按钮
';
// 5秒后移除提示
setTimeout(() => {
if (statusMsg && document.contains(statusMsg)) {
statusMsg.remove();
}
}, 5000);
}
return false;
}
}
}, 500);
},
// 处理确认对话框
handleConfirmDialog: function(statusMsg) {
EducationHelper.Logger.action("等待确认对话框...");
// 等待确认对话框出现
setTimeout(() => {
// 尝试查找确认按钮
let confirmButton = document.querySelector('.layui-layer-btn0, .layui-btn, [type="submit"]');
if (!confirmButton) {
// 更通用地查找确认按钮
const modalButtons = document.querySelectorAll('.modal-footer .btn, .layui-layer-btn .layui-layer-btn0, .dialog-footer .btn');
if (modalButtons.length > 0) {
confirmButton = modalButtons[0];
} else {
const buttons = document.querySelectorAll('button, a.btn, input[type="button"]');
for (const btn of buttons) {
const btnText = btn.textContent || btn.value || '';
if (btnText.includes('确定') || btnText.includes('确认') || btnText.includes('是')) {
confirmButton = btn;
break;
}
}
}
}
if (confirmButton) {
EducationHelper.Logger.action("找到确认按钮,确认提交");
// 更新状态提示
if (statusMsg) {
statusMsg.innerHTML = '找到确认按钮,正在确认提交...
';
}
// 点击确认按钮
confirmButton.click();
// 显示成功消息
if (statusMsg) {
statusMsg.innerHTML = '评价提交成功!
';
// 2秒后隐藏提示
setTimeout(() => {
if (statusMsg && document.contains(statusMsg)) {
statusMsg.remove();
}
}, 2000);
}
EducationHelper.Logger.success("已完成评价提交");
// 全屏成功提示
EducationHelper.UI.showMessage(`
✅
评价提交成功!
`, 'success', 2000);
// 如果处于自动模式,尝试自动返回列表页以继续评价
if (EducationHelper.Config.state.autoMode) {
// 查找返回按钮或列表链接
setTimeout(() => {
const backBtn = document.querySelector('a:contains("返回"), a:contains("列表"), a[href*="index"]');
if (backBtn) {
EducationHelper.Logger.action("找到返回按钮,自动返回列表页");
backBtn.click();
}
}, 2000);
}
return true;
} else {
EducationHelper.Logger.action("未找到确认按钮,可能评价已直接提交或需要手动确认");
// 提示用户可能需要手动确认
if (statusMsg) {
statusMsg.innerHTML = '可能需要手动确认提交,请检查是否有弹出确认窗口
';
// 5秒后移除提示
setTimeout(() => {
if (statusMsg && document.contains(statusMsg)) {
statusMsg.remove();
}
}, 5000);
}
return false;
}
}, 1000);
}
},
// 流程控制
process: {
// 启动自动评价流程
start: function() {
EducationHelper.Logger.action('开始评价流程...');
// 显示状态消息
EducationHelper.UI.showMessage(
'正在进行评价操作...
',
'info',
2000
);
// 1. 选择选项
EducationHelper.Evaluator.optionSelector.selectByLetter(
EducationHelper.Config.state.selectedOption
);
// 2. 填写评价内容
setTimeout(() => {
EducationHelper.Evaluator.contentFiller.fillContent(
document.getElementById('evaluationContent')?.value ||
EducationHelper.Config.content.evaluationComment
);
// 禁用开始按钮,防止重复点击
const startButton = document.getElementById('startEvaluation');
if (startButton) {
startButton.disabled = true;
startButton.style.opacity = '0.6';
startButton.textContent = '评价已开始';
}
// 3. 如果自动提交已启用,启动倒计时
if (EducationHelper.Config.state.autoSubmitEnabled) {
EducationHelper.Logger.action('已启用自动提交,开始倒计时...');
// 启动倒计时
EducationHelper.Evaluator.submitter.countdown.start(
EducationHelper.Config.timers.autoSubmitDelay / 1000,
// 倒计时结束回调
() => {
if (EducationHelper.Config.state.autoSubmitEnabled) {
EducationHelper.Logger.action('倒计时结束,自动提交评价');
// 提示用户即将提交
EducationHelper.UI.showMessage(
`⏱️ 倒计时结束
正在自动提交评价...
`,
'info',
2000
);
// 提交评价
setTimeout(() => {
EducationHelper.Evaluator.process.submit();
}, 2000);
}
}
);
}
}, 500);
},
// 提交评价
submit: function() {
EducationHelper.Logger.action('提交评价...');
// 保存评价内容到配置
const contentElement = document.getElementById('evaluationContent');
if (contentElement) {
EducationHelper.Config.content.evaluationComment = contentElement.value;
// 保存到localStorage
EducationHelper.Config.saveSettings();
}
// 再次确认文本框已填写
EducationHelper.Evaluator.contentFiller.fillContent();
// 查找并点击提交按钮
EducationHelper.Evaluator.submitter.findAndClickSubmitButton();
}
},
// UI生成 - iOS风格
generateUI: function() {
return `
⏱️ 等待提交: 120 秒
`;
},
// 事件绑定
bindEvents: function() {
// 选项单选按钮
const optionRadios = document.getElementsByName('evaluationOption');
optionRadios.forEach(radio => {
radio.addEventListener('change', function() {
EducationHelper.Config.state.selectedOption = this.value;
EducationHelper.Logger.action(`已选择${this.value}选项`);
// 保存选择到localStorage
EducationHelper.Config.saveSettings();
});
});
// 自动提交复选框
document.getElementById('autoSubmitEvaluation').addEventListener('change', function() {
EducationHelper.Config.state.autoSubmitEnabled = this.checked;
EducationHelper.Logger.action(`自动提交评价: ${this.checked ? '已启用' : '已禁用'}`);
});
// 评价内容输入框
document.getElementById('evaluationContent').addEventListener('input', function() {
EducationHelper.Config.content.evaluationComment = this.value;
});
// 选择选项按钮
document.getElementById('selectOptions').addEventListener('click', () => {
EducationHelper.Evaluator.optionSelector.selectByLetter(
EducationHelper.Config.state.selectedOption
);
// 如果启用了自动提交,则应用选项后自动提交
if (EducationHelper.Config.state.autoSubmitEnabled) {
EducationHelper.Logger.action('已启用自动提交,将在3秒后提交评价...');
setTimeout(() => {
EducationHelper.Evaluator.process.submit();
}, 3000);
}
});
// 立即提交评价按钮
document.getElementById('submitEvaluation').addEventListener('click', () => {
EducationHelper.Evaluator.process.submit();
});
// 开始评价按钮
document.getElementById('startEvaluation').addEventListener('click', () => {
EducationHelper.Evaluator.process.start();
});
},
// 初始化
init: function() {
if (!EducationHelper.Config.pageType.isEvaluationPage) return;
EducationHelper.Logger.action('初始化评估模块...');
// 检查localStorage中是否存在autoMode标记
if (EducationHelper.Config.state.autoMode) {
EducationHelper.Logger.action('检测到全自动模式,自动开始评价流程');
// 延迟执行,确保页面已完全加载
setTimeout(() => {
// 自动执行评价流程
this.process.start();
}, 1000);
}
return this;
}
},
// 评估列表模块 - 处理评估列表页面
EvaluationList: {
// 进度统计
progress: {
total: 0,
completed: 0,
// 统计评价进度
updateProgress: function() {
try {
// 查找所有评估按钮
const evaluationButtons = document.querySelectorAll('button, a');
let totalCount = 0;
let completedCount = 0;
// 统计包含"评估"的按钮
evaluationButtons.forEach(btn => {
const text = btn.textContent || btn.innerText || '';
if (text.includes('评估') || text.includes('评价')) {
totalCount++;
// 检查是否已完成(按钮被禁用或包含完成标记)
if (btn.disabled ||
text.includes('已评') ||
text.includes('完成') ||
btn.classList.contains('disabled') ||
btn.style.display === 'none') {
completedCount++;
}
}
});
// 如果通过按钮统计不准确,尝试其他方法
if (totalCount === 0) {
// 查找表格行或列表项
const rows = document.querySelectorAll('tr, .list-item, .evaluation-item');
rows.forEach(row => {
const text = row.textContent || row.innerText || '';
if (text.includes('评估') || text.includes('评价') || text.includes('教师')) {
totalCount++;
if (text.includes('已评') || text.includes('完成') || text.includes('已完成')) {
completedCount++;
}
}
});
}
this.total = totalCount;
this.completed = completedCount;
EducationHelper.Logger.debug(`进度统计: ${completedCount}/${totalCount}`);
// 更新UI显示
this.updateUI();
return { total: totalCount, completed: completedCount };
} catch (error) {
EducationHelper.Logger.error('统计评价进度时出错', error);
return { total: 0, completed: 0 };
}
},
// 更新进度显示UI
updateUI: function() {
const progressDiv = document.getElementById('evaluationProgress');
if (!progressDiv) return;
const percentage = this.total > 0 ? Math.round((this.completed / this.total) * 100) : 0;
const isCompleted = this.completed === this.total && this.total > 0;
progressDiv.innerHTML = `
📊 评价进度
${this.completed}/${this.total}
${isCompleted ?
'🎉 所有评价已完成!' :
`完成度: ${percentage}% ${this.total > 0 ? `(还剩 ${this.total - this.completed} 个)` : ''}`
}
`;
}
},
// 自动点击功能
autoClicker: {
// 开始自动点击倒计时
startCountdown: function() {
EducationHelper.Logger.action(`开始自动点击倒计时,${EducationHelper.Config.timers.autoClickEvaluationDelay/1000}秒后开始执行...`);
// 设置初始倒计时值
const countdownElement = document.getElementById('countdownValue');
if (!countdownElement) return false;
let secondsLeft = EducationHelper.Config.timers.autoClickEvaluationDelay / 1000;
countdownElement.textContent = secondsLeft;
// 清除之前的计时器
if (window.autoClickCountdownTimer) {
clearInterval(window.autoClickCountdownTimer);
}
// 创建全局标记来表示停止状态
window.autoClickStopped = false;
// 创建新的倒计时
window.autoClickCountdownTimer = setInterval(() => {
// 每次检查是否已停止
if (window.autoClickStopped) {
clearInterval(window.autoClickCountdownTimer);
window.autoClickCountdownTimer = null;
EducationHelper.Logger.action('倒计时已被手动停止');
return;
}
secondsLeft -= 1;
countdownElement.textContent = secondsLeft;
// 倒计时结束,执行自动点击
if (secondsLeft <= 0) {
clearInterval(window.autoClickCountdownTimer);
window.autoClickCountdownTimer = null;
// 再次检查是否仍然启用了自动点击和未被停止
if ((EducationHelper.Config.state.autoClickEvaluationEnabled || EducationHelper.Config.state.autoMode) && !window.autoClickStopped) {
EducationHelper.Logger.action('倒计时结束,开始扫描评估按钮...');
// 更新倒计时文本
const countdownDiv = document.getElementById('countdownDiv');
if (countdownDiv) {
countdownDiv.innerHTML = '自动操作开始执行...';
}
// 延迟执行扫描,让用户有机会看到状态更新
setTimeout(() => {
// 再次检查,确保在延迟期间没有被停止
if (!window.autoClickStopped) {
// 扫描并点击评估按钮
EducationHelper.EvaluationList.scanner.scanAndClick();
// 扫描完成后隐藏倒计时区域
setTimeout(() => {
if (countdownDiv) {
countdownDiv.style.display = 'none';
}
// 自动模式下不关闭开关,保持自动状态
if (!EducationHelper.Config.state.autoMode) {
EducationHelper.Config.state.autoClickEvaluationEnabled = false;
const checkbox = document.getElementById('autoClickEvaluation');
if (checkbox) checkbox.checked = false;
}
}, 2000);
} else {
EducationHelper.Logger.action('在延迟期间检测到停止请求,取消自动操作');
if (countdownDiv) {
countdownDiv.style.display = 'none';
}
}
}, 500);
} else {
EducationHelper.Logger.action('倒计时结束,但自动点击已被禁用');
const countdownDiv = document.getElementById('countdownDiv');
if (countdownDiv) {
countdownDiv.style.display = 'none';
}
}
}
}, 1000);
return true;
}
},
// 扫描与点击
scanner: {
// 扫描评估按钮并点击(仅自动模式)
scanAndClick: function() {
EducationHelper.Logger.action('自动扫描评估按钮开始...');
// 更新进度统计
EducationHelper.EvaluationList.progress.updateProgress();
// 获取所有按钮
const buttons = document.querySelectorAll('button');
// 找到包含"评估"的按钮
let evaluationButtons = [];
buttons.forEach(button => {
if ((button.innerText && button.innerText.includes('评估')) ||
(button.textContent && button.textContent.includes('评估'))) {
evaluationButtons.push(button);
EducationHelper.Logger.debug(`评估按钮: ${button.outerHTML}`);
}
});
// 如果找不到评估按钮,尝试链接
if (evaluationButtons.length === 0) {
const links = document.querySelectorAll('a');
links.forEach(link => {
if ((link.innerText && link.innerText.includes('评估')) ||
(link.textContent && link.textContent.includes('评估'))) {
evaluationButtons.push(link);
EducationHelper.Logger.debug(`评估链接: ${link.outerHTML}`);
}
});
}
EducationHelper.Logger.action(`找到 ${evaluationButtons.length} 个评估按钮`);
// 自动模式处理
if (evaluationButtons.length > 0) {
// 优先点击带有"评估"文本的按钮
const buttonToClick = evaluationButtons[0];
// 创建简洁的倒计时提示
let countdownSeconds = 3; // 缩短倒计时时间
// 显示简洁的状态提示
const statusMsg = EducationHelper.UI.showMessage(`
🎯 找到评估按钮
将在 ${countdownSeconds} 秒后点击
`, 'info', 0);
// 开始倒计时
const countdownTimer = setInterval(() => {
countdownSeconds--;
// 检查是否已手动停止
if (window.autoClickStopped) {
clearInterval(countdownTimer);
if (statusMsg && document.contains(statusMsg)) {
statusMsg.remove();
}
return;
}
const countdownElement = document.getElementById('clickCountdown');
if (countdownElement) {
countdownElement.textContent = countdownSeconds;
}
if (countdownSeconds <= 0) {
clearInterval(countdownTimer);
// 更新提示信息
if (statusMsg && document.contains(statusMsg)) {
statusMsg.innerHTML = '🚀 正在点击评估按钮...
';
}
// 点击评估按钮
setTimeout(() => {
if (!window.autoClickStopped) {
this.clickButton(buttonToClick);
// 移除状态提示
if (statusMsg && document.contains(statusMsg)) {
statusMsg.remove();
}
}
}, 500);
}
}, 1000);
} else {
EducationHelper.UI.showMessage('未找到评估按钮', 'warning', 3000);
}
},
// 安全点击按钮
clickButton: function(button) {
EducationHelper.Logger.action(`点击按钮: ${button.outerHTML}`);
// 尝试使用默认点击事件
try {
button.click();
EducationHelper.Logger.success('已点击按钮');
return true;
} catch (error) {
EducationHelper.Logger.warn('直接点击失败,尝试使用替代方法:', error);
}
// 尝试触发合成事件
try {
// 创建鼠标事件并触发
const evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
// 分发事件
button.dispatchEvent(evt);
EducationHelper.Logger.success('已通过事件触发点击按钮');
return true;
} catch (error) {
EducationHelper.Logger.error('无法点击按钮:', error);
return false;
}
}
},
// 自动模式控制
autoMode: {
// 启用自动模式
enable: function() {
EducationHelper.Config.state.autoMode = true;
EducationHelper.Logger.action('全自动模式已启用');
// 将autoMode状态保存到localStorage
EducationHelper.Config.saveSettings();
// 自动启用评估按钮点击
EducationHelper.Config.state.autoClickEvaluationEnabled = true;
const checkbox = document.getElementById('autoClickEvaluation');
if (checkbox) checkbox.checked = true;
// 显示倒计时并开始自动点击
const countdownDiv = document.getElementById('countdownDiv');
if (countdownDiv) {
countdownDiv.style.display = 'block';
countdownDiv.innerHTML = `
🚀 全自动模式已启用!
自动操作将在 ${EducationHelper.Config.timers.autoClickEvaluationDelay/1000} 秒后开始
`;
}
// 开始倒计时
EducationHelper.EvaluationList.autoClicker.startCountdown();
// 显示提示消息
EducationHelper.UI.showMessage(`
✅ 全自动模式已启用
系统将自动完成整个评价流程:
1. 自动点击"评估"按钮 ⏳
2. 自动选择选项和填写内容 ⏳
3. 自动提交评价 ⏳
`, 'success', 5000);
return true;
},
// 禁用自动模式
disable: function() {
EducationHelper.Config.state.autoMode = false;
EducationHelper.Logger.action('全自动模式已禁用');
// 将autoMode状态保存到localStorage
EducationHelper.Config.saveSettings();
// 立即设置停止标记
window.autoClickStopped = true;
// 立即停止倒计时
if (window.autoClickCountdownTimer) {
clearInterval(window.autoClickCountdownTimer);
window.autoClickCountdownTimer = null;
}
// 关闭自动点击评估按钮功能
EducationHelper.Config.state.autoClickEvaluationEnabled = false;
const checkbox = document.getElementById('autoClickEvaluation');
if (checkbox) checkbox.checked = false;
// 隐藏倒计时区域
const countdownDiv = document.getElementById('countdownDiv');
if (countdownDiv) {
countdownDiv.style.display = 'none';
}
// 显示停止提示
EducationHelper.UI.showMessage(`
⛔ 全自动模式已停止
自动评价流程已终止,您可以手动操作
`, 'error', 3000);
return true;
}
},
// UI生成 - iOS风格
generateUI: function() {
return `
⚠️ 注意事项
• 自动点击功能默认关闭,需手动启用
• 全自动模式将完成所有评价流程
• 自动操作将在 ${EducationHelper.Config.timers.autoClickEvaluationDelay/1000}秒 后开始执行
• 操作过程中可随时取消
⏱️ 自动操作倒计时
${EducationHelper.Config.timers.autoClickEvaluationDelay/1000} 秒
`;
},
// 事件绑定
bindEvents: function() {
// 自动点击评估按钮复选框
document.getElementById('autoClickEvaluation').addEventListener('change', function() {
EducationHelper.Config.state.autoClickEvaluationEnabled = this.checked;
EducationHelper.Logger.action(`自动点击评估按钮: ${this.checked ? '已启用' : '已禁用'}`);
// 显示或隐藏倒计时区域
const countdownDiv = document.getElementById('countdownDiv');
if (this.checked) {
countdownDiv.style.display = 'block';
EducationHelper.EvaluationList.autoClicker.startCountdown();
} else {
countdownDiv.style.display = 'none';
// 如果有正在进行的倒计时,取消它
if (window.autoClickCountdownTimer) {
clearInterval(window.autoClickCountdownTimer);
window.autoClickCountdownTimer = null;
}
}
});
// 全自动模式按钮
document.getElementById('autoModeButton').addEventListener('click', function() {
// 根据当前状态切换自动模式
if (EducationHelper.Config.state.autoMode) {
EducationHelper.EvaluationList.autoMode.disable();
} else {
EducationHelper.EvaluationList.autoMode.enable();
}
// 更新按钮样式
this.style.background = EducationHelper.Config.state.autoMode ?
'linear-gradient(135deg, #4caf50, #2e7d32)' :
'linear-gradient(135deg, #2196f3, #0d47a1)';
this.innerHTML = `
${EducationHelper.Config.state.autoMode ? '✅' : '🚀'}
${EducationHelper.Config.state.autoMode ? '停止全自动模式' : '启用全自动模式'}
${!EducationHelper.Config.state.autoMode ? '(自动评估、选择、提交)' : ''}
`;
});
// 调试模式复选框
document.getElementById('debugMode').addEventListener('change', function() {
EducationHelper.Config.state.debugMode = this.checked;
EducationHelper.Logger.action(`调试模式: ${this.checked ? '已启用' : '已禁用'}`);
// 显示/隐藏调试面板
const debugPanel = document.getElementById('debugInfo');
if (debugPanel) {
debugPanel.style.display = this.checked ? 'block' : 'none';
}
// 如果启用调试模式,输出页面基本信息
if (this.checked) {
EducationHelper.Logger.debug('调试模式已启用');
EducationHelper.Logger.debug(`当前URL: ${window.location.href}`);
EducationHelper.Logger.debug(`页面标题: ${document.title}`);
EducationHelper.Logger.debug(`jQuery可用: ${typeof $ !== 'undefined'}`);
}
});
},
// 初始化
init: function() {
if (!EducationHelper.Config.pageType.isEvaluationListPage) return;
EducationHelper.Logger.action('初始化评估列表模块...');
// 初始化进度统计
setTimeout(() => {
this.progress.updateProgress();
// 定期更新进度(每5秒)
setInterval(() => {
this.progress.updateProgress();
}, 5000);
}, 1000);
// 如果启用了自动点击,则设置倒计时
if (EducationHelper.Config.state.autoClickEvaluationEnabled || EducationHelper.Config.state.autoMode) {
// 等待UI元素创建完成后启动倒计时
setTimeout(() => {
const countdownDiv = document.getElementById('countdownDiv');
if (countdownDiv) {
countdownDiv.style.display = 'block';
// 开始倒计时
this.autoClicker.startCountdown();
}
}, 500);
}
return this;
}
},
};
// 初始化配置
EducationHelper.Config.init();
// 主入口点 - 脚本初始化
function init() {
console.log('齐大教务助手启动中...');
// 等待DOM加载完成
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initAfterDOMLoaded);
} else {
initAfterDOMLoaded();
}
}
// DOM加载完成后初始化
function initAfterDOMLoaded() {
// 创建UI界面
EducationHelper.UI.create();
// 根据页面类型初始化相应模块
initModulesByPageType();
}
// 根据页面类型初始化模块
function initModulesByPageType() {
const config = EducationHelper.Config;
if (config.pageType.isCoursePage) {
// 初始化抢课模块
EducationHelper.CourseGrabber.init();
// 生成UI内容
EducationHelper.UI.elements.content.innerHTML = EducationHelper.CourseGrabber.generateUI();
// 绑定事件
EducationHelper.CourseGrabber.bindEvents();
}
else if (config.pageType.isEvaluationPage) {
// 评估页面初始化代码
EducationHelper.Evaluator.init();
EducationHelper.UI.elements.content.innerHTML = EducationHelper.Evaluator.generateUI();
EducationHelper.Evaluator.bindEvents();
}
else if (config.pageType.isEvaluationListPage) {
// 评估列表页面初始化代码
EducationHelper.EvaluationList.init();
EducationHelper.UI.elements.content.innerHTML = EducationHelper.EvaluationList.generateUI();
EducationHelper.EvaluationList.bindEvents();
}
else {
// 不支持的页面
EducationHelper.UI.elements.content.innerHTML = `
`;
}
}
// 启动脚本
init();
})();