// ==UserScript== // @name 三峡大学科技学院自动评教脚本 // @namespace http://tampermonkey.net/ // @version 1.0.3 // @description 自动评教脚本,支持自动/手动提交模式,可自定义评教内容,含页面检测功能 // @author 满满. // @match http://kjjw.ctgu.edu.cn/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_notification // @run-at document-end // ==/UserScript== (function() { 'use strict'; let autoSubmit = false; let isProcessing = false; let countdownInterval = null; let shouldStop = false; let q14Text = GM_getValue('q14Text', '无'); let q15Text = GM_getValue('q15Text', '老师教学认真负责,课程内容充实,讲解清晰易懂。'); let completedCount = 0; let totalCount = 0; let errorLogs = GM_getValue('errorLogs', []); let settingsClickCount = 0; let settingsClickTimer = null; let isMinimized = true; function createControlPanel() { const panel = document.createElement('div'); panel.id = 'auto-eval-panel'; panel.innerHTML = `
📝 0/0
`; document.body.appendChild(panel); const style = document.createElement('style'); style.textContent = ` #auto-eval-panel { position: fixed; top: 20px; right: 20px; width: 280px; background: linear-gradient(135deg, #fafaf9 0%, #f5f5f4 50%, #e7e5e4 100%); border-radius: 16px; box-shadow: 0 8px 32px rgba(0,0,0,0.08), 0 2px 8px rgba(0,0,0,0.04), inset 0 1px 0 rgba(255,255,255,0.6); z-index: 99999; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; user-select: none; backdrop-filter: blur(10px); overflow: hidden; } #auto-eval-panel::before { content: ''; position: absolute; top: -50%; left: -50%; width: 200%; height: 200%; background: radial-gradient(circle at 30% 30%, rgba(245, 158, 11, 0.08) 0%, transparent 50%), radial-gradient(circle at 70% 70%, rgba(217, 119, 6, 0.05) 0%, transparent 50%); pointer-events: none; z-index: 0; } .floating-ball { position: fixed; top: 20px; right: 20px; width: 60px; height: 60px; cursor: pointer; z-index: 99999; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } .floating-ball:hover { transform: scale(1.1); } .ball-progress-ring { position: relative; width: 100%; height: 100%; } .progress-ring { position: absolute; top: 0; left: 0; filter: drop-shadow(0 2px 8px rgba(217, 119, 6, 0.3)); } .progress-ring-circle { transition: stroke-dashoffset 0.5s ease; } .ball-content { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; justify-content: center; } .ball-icon { font-size: 18px; margin-bottom: 2px; } .ball-text { font-size: 11px; font-weight: 600; color: #d97706; } .panel-content-wrapper { width: 100%; height: 100%; display: flex; flex-direction: column; } .panel-header { background: linear-gradient(135deg, #d97706 0%, #ea580c 100%); color: #fafaf9; padding: 16px 20px; border-radius: 16px 16px 0 0; display: flex; justify-content: space-between; align-items: center; font-weight: 600; cursor: move; position: relative; z-index: 1; box-shadow: inset 0 1px 0 rgba(255,255,255,0.2); } .header-actions { display: flex; align-items: center; gap: 8px; } .minimize-btn { cursor: pointer; font-size: 20px; line-height: 1; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s ease; background: rgba(255,255,255,0.15); } .minimize-btn:hover { background: rgba(255,255,255,0.25); } .settings-btn { cursor: pointer; font-size: 18px; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s ease; background: rgba(255,255,255,0.15); } .settings-btn:hover { background: rgba(255,255,255,0.25); transform: rotate(90deg); } .panel-header::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 1px; background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); } .panel-title { flex: 1; font-size: 15px; letter-spacing: 0.3px; } .close-btn { cursor: pointer; font-size: 24px; line-height: 1; margin-left: 12px; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s ease; background: rgba(255,255,255,0.15); } .close-btn:hover { background: rgba(255,255,255,0.25); transform: rotate(90deg); } .panel-content { padding: 20px; position: relative; z-index: 1; } .control-row { display: flex; align-items: center; margin-bottom: 16px; } .switch { position: relative; display: inline-block; width: 52px; height: 26px; margin-right: 12px; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(135deg, #d6d3d1 0%, #a8a29e 100%); transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); border-radius: 26px; box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); } .slider:before { position: absolute; content: ""; height: 20px; width: 20px; left: 3px; bottom: 3px; background: linear-gradient(135deg, #fafaf9 0%, #e7e5e4 100%); transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); border-radius: 50%; box-shadow: 0 2px 4px rgba(0,0,0,0.15); } input:checked + .slider { background: linear-gradient(135deg, #d97706 0%, #ea580c 100%); box-shadow: 0 2px 8px rgba(217, 119, 6, 0.4); } input:checked + .slider:before { transform: translateX(26px); box-shadow: 0 2px 8px rgba(217, 119, 6, 0.3); } .label-text { font-size: 14px; color: #44403c; font-weight: 500; } .btn { flex: 1; margin: 0 5px; padding: 10px 18px; border: none; border-radius: 10px; cursor: pointer; font-size: 14px; font-weight: 500; color: #fafaf9; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); box-shadow: 0 2px 8px rgba(0,0,0,0.1); } .btn:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.15); } .btn:active { transform: translateY(0); } .btn-primary { background: linear-gradient(135deg, #d97706 0%, #ea580c 100%); } .btn-primary:hover { background: linear-gradient(135deg, #b45309 0%, #c2410c 100%); box-shadow: 0 4px 16px rgba(217, 119, 6, 0.3); } .btn-danger { background: linear-gradient(135deg, #78716c 0%, #57534e 100%); } .btn-danger:hover { background: linear-gradient(135deg, #57534e 0%, #44403c 100%); box-shadow: 0 4px 16px rgba(87, 83, 78, 0.3); } .btn:disabled { background: linear-gradient(135deg, #d6d3d1 0%, #a8a29e 100%); cursor: not-allowed; transform: none; box-shadow: none; color: #78716c; } .btn-small { padding: 6px 12px; font-size: 12px; margin-left: 10px; background: linear-gradient(135deg, #78716c 0%, #57534e 100%); } .btn-small:hover { background: linear-gradient(135deg, #57534e 0%, #44403c 100%); box-shadow: 0 2px 8px rgba(87, 83, 78, 0.3); } .countdown-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; padding: 12px 14px; background: linear-gradient(135deg, rgba(251, 191, 36, 0.15) 0%, rgba(245, 158, 11, 0.1) 100%); border: 1px solid rgba(245, 158, 11, 0.3); border-radius: 10px; backdrop-filter: blur(5px); } #countdown-text { font-size: 13px; color: #92400e; font-weight: 600; } .progress-row { margin-bottom: 16px; } .progress-info { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; } .progress-label { font-size: 13px; color: #44403c; font-weight: 500; } .progress-text { font-size: 13px; color: #d97706; font-weight: 600; } .progress-bar-container { width: 100%; height: 8px; background: linear-gradient(135deg, #d6d3d1 0%, #a8a29e 100%); border-radius: 4px; overflow: hidden; box-shadow: inset 0 1px 3px rgba(0,0,0,0.1); } .progress-bar { height: 100%; width: 0%; background: linear-gradient(135deg, #d97706 0%, #ea580c 100%); border-radius: 4px; transition: width 0.3s ease; box-shadow: 0 0 8px rgba(217, 119, 6, 0.4); } .status-row { margin-top: 20px; padding-top: 16px; border-top: 1px solid rgba(0,0,0,0.06); } #status-text { font-size: 13px; color: #57534e; font-weight: 400; line-height: 1.5; } @media (max-width: 768px) { #auto-eval-panel { width: 260px; right: 10px; top: 10px; } .panel-header { padding: 14px 16px; } .panel-content { padding: 16px; } .btn { padding: 9px 14px; font-size: 13px; } } .settings-panel { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(135deg, #fafaf9 0%, #f5f5f4 50%, #e7e5e4 100%); border-radius: 16px; z-index: 2; display: flex; flex-direction: column; animation: slideIn 0.3s ease; } @keyframes slideIn { from { opacity: 0; transform: translateX(20px); } to { opacity: 1; transform: translateX(0); } } .settings-header { background: linear-gradient(135deg, #d97706 0%, #ea580c 100%); color: #fafaf9; padding: 16px 20px; border-radius: 16px 16px 0 0; display: flex; justify-content: space-between; align-items: center; font-weight: 600; box-shadow: inset 0 1px 0 rgba(255,255,255,0.2); } .settings-title { font-size: 15px; letter-spacing: 0.3px; } .settings-close-btn { cursor: pointer; font-size: 24px; line-height: 1; width: 28px; height: 28px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.3s ease; background: rgba(255,255,255,0.15); } .settings-close-btn:hover { background: rgba(255,255,255,0.25); transform: rotate(90deg); } .settings-content { padding: 20px; flex: 1; overflow-y: auto; } .settings-item { margin-bottom: 20px; } .settings-label { display: block; font-size: 14px; color: #44403c; font-weight: 500; margin-bottom: 8px; } .settings-textarea { width: 100%; padding: 12px; border: 1px solid #d6d3d1; border-radius: 10px; font-size: 13px; color: #57534e; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; resize: vertical; background: linear-gradient(135deg, #fafaf9 0%, #f5f5f4 100%); transition: all 0.3s ease; box-shadow: inset 0 1px 3px rgba(0,0,0,0.06); } .settings-textarea:focus { outline: none; border-color: #d97706; box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.1), inset 0 1px 3px rgba(0,0,0,0.06); } .settings-textarea::placeholder { color: #a8a29e; } .settings-actions { display: flex; gap: 10px; margin-top: 24px; } .settings-actions .btn { margin: 0; } .log-panel { position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: linear-gradient(135deg, #fafaf9 0%, #f5f5f4 50%, #e7e5e4 100%); border-radius: 16px; display: flex; flex-direction: column; overflow: hidden; } .log-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid rgba(0,0,0,0.08); background: linear-gradient(135deg, rgba(251, 191, 36, 0.1) 0%, rgba(245, 158, 11, 0.05) 100%); } .log-title { font-size: 15px; font-weight: 600; color: #44403c; } .log-actions { display: flex; gap: 12px; align-items: center; } .log-clear-btn { font-size: 13px; color: #d97706; cursor: pointer; padding: 4px 12px; border-radius: 6px; background: rgba(217, 119, 6, 0.1); transition: all 0.2s ease; } .log-clear-btn:hover { background: rgba(217, 119, 6, 0.2); } .log-close-btn { font-size: 24px; color: #78716c; cursor: pointer; transition: all 0.2s ease; } .log-close-btn:hover { color: #44403c; transform: rotate(90deg); } .log-content { flex: 1; overflow-y: auto; padding: 12px; max-height: 320px; } .log-content::-webkit-scrollbar { width: 6px; } .log-content::-webkit-scrollbar-track { background: rgba(0,0,0,0.05); border-radius: 3px; } .log-content::-webkit-scrollbar-thumb { background: rgba(168, 162, 158, 0.5); border-radius: 3px; } .log-empty { text-align: center; padding: 40px 20px; color: #a8a29e; font-size: 14px; } .log-item { background: linear-gradient(135deg, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0.4) 100%); border: 1px solid rgba(0,0,0,0.08); border-radius: 10px; padding: 12px; margin-bottom: 10px; box-shadow: 0 2px 8px rgba(0,0,0,0.04); } .log-time { font-size: 11px; color: #a8a29e; margin-bottom: 4px; } .log-message { font-size: 13px; color: #44403c; font-weight: 500; margin-bottom: 6px; line-height: 1.4; } .log-url { font-size: 11px; color: #78716c; word-break: break-all; font-family: monospace; } .warning-toast { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%) scale(0.9); background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); border: 2px solid #f59e0b; border-radius: 12px; padding: 20px 24px; display: flex; align-items: center; gap: 12px; box-shadow: 0 10px 40px rgba(245, 158, 11, 0.3); z-index: 100000; opacity: 0; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); max-width: 320px; } .warning-toast.toast-show { opacity: 1; transform: translate(-50%, -50%) scale(1); } .toast-icon { font-size: 28px; flex-shrink: 0; } .toast-message { font-size: 14px; color: #92400e; font-weight: 500; line-height: 1.5; } `; document.head.appendChild(style); makeDraggable(panel); document.getElementById('floating-ball').addEventListener('click', function() { document.getElementById('floating-ball').style.display = 'none'; document.getElementById('panel-content-wrapper').style.display = 'flex'; isMinimized = false; }); document.querySelector('.minimize-btn').addEventListener('click', function() { document.getElementById('panel-content-wrapper').style.display = 'none'; document.getElementById('floating-ball').style.display = 'block'; isMinimized = true; }); document.getElementById('auto-submit-toggle').addEventListener('change', function() { autoSubmit = this.checked; updateStatus(`自动提交: ${autoSubmit ? '开启' : '关闭'}`); }); document.getElementById('start-eval-btn').addEventListener('click', startEvaluation); document.getElementById('stop-eval-btn').addEventListener('click', stopEvaluation); document.querySelector('.close-btn').addEventListener('click', function() { document.getElementById('floating-ball').style.display = 'none'; document.getElementById('panel-content-wrapper').style.display = 'none'; }); document.querySelector('.settings-btn').addEventListener('click', function() { settingsClickCount++; if (settingsClickCount === 1) { settingsClickTimer = setTimeout(() => { settingsClickCount = 0; document.getElementById('settings-content').style.display = 'block'; document.getElementById('log-panel').style.display = 'none'; document.getElementById('settings-panel').style.display = 'flex'; }, 300); } else if (settingsClickCount === 2) { clearTimeout(settingsClickTimer); settingsClickCount = 0; document.getElementById('settings-content').style.display = 'none'; document.getElementById('log-panel').style.display = 'flex'; document.getElementById('settings-panel').style.display = 'flex'; updateLogPanel(); } }); document.querySelector('.settings-close-btn').addEventListener('click', function() { document.getElementById('settings-panel').style.display = 'none'; }); document.querySelector('.log-close-btn').addEventListener('click', function() { document.getElementById('settings-panel').style.display = 'none'; }); document.getElementById('clear-logs-btn').addEventListener('click', function() { errorLogs = []; GM_setValue('errorLogs', errorLogs); updateLogPanel(); }); document.getElementById('save-settings-btn').addEventListener('click', function() { q14Text = document.getElementById('q14-textarea').value.trim(); q15Text = document.getElementById('q15-textarea').value.trim(); GM_setValue('q14Text', q14Text); GM_setValue('q15Text', q15Text); updateStatus('设置已保存'); document.getElementById('settings-panel').style.display = 'none'; setTimeout(() => { updateStatus('就绪'); }, 2000); }); document.getElementById('reset-settings-btn').addEventListener('click', function() { q14Text = '无'; q15Text = '老师教学认真负责,课程内容充实,讲解清晰易懂。'; document.getElementById('q14-textarea').value = q14Text; document.getElementById('q15-textarea').value = q15Text; GM_setValue('q14Text', q14Text); GM_setValue('q15Text', q15Text); updateStatus('已恢复默认设置'); setTimeout(() => { updateStatus('就绪'); }, 2000); }); } function makeDraggable(element) { const header = element.querySelector('.panel-header'); const floatingBall = element.querySelector('.floating-ball'); let isDragging = false; let currentX; let currentY; let initialX; let initialY; let xOffset = 0; let yOffset = 0; if (header) { header.addEventListener('mousedown', dragStart); } if (floatingBall) { floatingBall.addEventListener('mousedown', dragStart); } document.addEventListener('mousemove', drag); document.addEventListener('mouseup', dragEnd); function dragStart(e) { if (e.target.classList.contains('close-btn') || e.target.classList.contains('settings-btn') || e.target.classList.contains('minimize-btn')) return; const settingsPanel = document.getElementById('settings-panel'); if (settingsPanel && settingsPanel.style.display === 'flex') return; initialX = e.clientX - xOffset; initialY = e.clientY - yOffset; if (e.target === header || (header && header.contains(e.target)) || e.target === floatingBall || (floatingBall && floatingBall.contains(e.target))) { isDragging = true; } } function drag(e) { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; setTranslate(currentX, currentY, element); } } function dragEnd(e) { initialX = currentX; initialY = currentY; isDragging = false; } function setTranslate(xPos, yPos, el) { el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`; } } function updateStatus(text) { const statusEl = document.getElementById('status-text'); if (statusEl) { statusEl.textContent = text; } } function showWarningToast(message) { const existingToast = document.getElementById('warning-toast'); if (existingToast) { existingToast.remove(); } const toast = document.createElement('div'); toast.id = 'warning-toast'; toast.className = 'warning-toast'; toast.innerHTML = `
⚠️
${message}
`; document.body.appendChild(toast); setTimeout(() => { toast.classList.add('toast-show'); }, 10); setTimeout(() => { toast.classList.remove('toast-show'); setTimeout(() => { toast.remove(); }, 300); }, 3000); } function isEvaluationPage() { return document.querySelector('footer.saveBtn') !== null; } function isListPage() { const url = window.location.href; return url.includes('/jwapp/sys/wspjyyapp/') && url.includes('#/xspj') && document.querySelector('.pj-card') !== null; } function fillEvaluationForm() { updateStatus('正在填写评教表单...'); const radioGroups = document.querySelectorAll('.bh-radio-group-h'); radioGroups.forEach(group => { const firstRadio = group.querySelector('input[type="radio"]'); if (firstRadio) { firstRadio.checked = true; } }); const q14Container = document.querySelector('.textareaContainter[data-x-zbdm="cc325d778b824abcb8d8c97d08511766"]'); if (q14Container) { const q14Textarea = q14Container.querySelector('textarea[name="YLCS"]'); if (q14Textarea) { q14Textarea.value = q14Text; } } const q15Container = document.querySelector('.textareaContainter[data-x-zbdm="3c5353b039594a3eb0df69dab191bb6e"]'); if (q15Container) { const q15Textarea = q15Container.querySelector('textarea[name="YLCS"]'); if (q15Textarea) { q15Textarea.value = q15Text; } } updateStatus('表单填写完成'); return true; } function submitEvaluation() { const submitBtn = document.querySelector('footer.saveBtn a[data-action="提交"]'); if (submitBtn) { submitBtn.click(); return true; } return false; } function returnToList() { const backBtn = document.querySelector('.back-img'); if (backBtn) { backBtn.click(); return true; } return false; } function clickNextTeacher() { const firstEvalBtn = document.querySelector('.card-btn[data-action="gcpj立即评教"]'); if (firstEvalBtn) { firstEvalBtn.click(); return true; } return false; } function getPendingTeacherCount() { const cards = document.querySelectorAll('.pj-card'); return cards.length; } function updateProgress() { const progressBar = document.getElementById('progress-bar'); const progressText = document.getElementById('progress-text'); const ballText = document.getElementById('ball-text'); const progressRingCircle = document.querySelector('.progress-ring-circle'); if (progressBar && progressText) { const percentage = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0; progressBar.style.width = `${percentage}%`; progressText.textContent = `${completedCount}/${totalCount}`; } if (ballText) { ballText.textContent = `${completedCount}/${totalCount}`; } if (progressRingCircle) { const percentage = totalCount > 0 ? Math.round((completedCount / totalCount) * 100) : 0; const circumference = 163.36; const offset = circumference - (percentage / 100) * circumference; progressRingCircle.style.strokeDashoffset = offset; } } function logError(message) { const errorLog = { time: new Date().toLocaleString(), message: message, url: window.location.href }; errorLogs.push(errorLog); GM_setValue('errorLogs', errorLogs); GM_notification({ title: '评教错误', text: message, timeout: 5000 }); updateLogPanel(); } function updateLogPanel() { const logContent = document.getElementById('log-content'); if (logContent) { if (errorLogs.length === 0) { logContent.innerHTML = '
暂无错误日志
'; } else { logContent.innerHTML = errorLogs.map(log => `
${log.time}
${log.message}
${log.url}
`).join(''); } } } function showNotification(title, text) { GM_notification({ title: title, text: text, timeout: 5000 }); } async function startEvaluation() { if (isProcessing) return; if (!isListPage()) { updateStatus('⚠️ 请先前往待评教老师列表页面'); showWarningToast('请先前往待评教老师列表页面再开始评教'); return; } isProcessing = true; document.getElementById('start-eval-btn').disabled = true; document.getElementById('stop-eval-btn').disabled = false; try { if (isEvaluationPage()) { await processEvaluationPage(); } else if (isListPage()) { await processListPage(); } else { updateStatus('当前页面不是评教页面或列表页面'); stopEvaluation(); } } catch (error) { updateStatus(`错误: ${error.message}`); stopEvaluation(); } } async function processEvaluationPage() { updateStatus('正在处理评教页面...'); try { fillEvaluationForm(); if (autoSubmit) { await startCountdownAndSubmit(); } else { updateStatus('表单已填写,请手动提交'); } } catch (error) { logError(`评教页面处理失败: ${error.message}`); stopEvaluation(); } } async function startCountdownAndSubmit() { return new Promise((resolve) => { const countdownRow = document.getElementById('countdown-row'); const countdownText = document.getElementById('countdown-text'); const cancelBtn = document.getElementById('cancel-countdown-btn'); let seconds = 3; shouldStop = false; countdownRow.style.display = 'flex'; countdownText.textContent = `提交倒计时: ${seconds}秒`; countdownInterval = setInterval(() => { seconds--; countdownText.textContent = `提交倒计时: ${seconds}秒`; if (shouldStop) { clearInterval(countdownInterval); countdownRow.style.display = 'none'; updateStatus('已取消提交'); stopEvaluation(); resolve(); return; } if (seconds <= 0) { clearInterval(countdownInterval); countdownRow.style.display = 'none'; submitWithConfirm(); resolve(); } }, 1000); cancelBtn.onclick = function() { shouldStop = true; }; }); } async function submitWithConfirm() { updateStatus('正在提交评教...'); if (submitEvaluation()) { updateStatus('等待确认弹窗...'); await waitForConfirmDialog(); } else { logError('提交失败,无法找到提交按钮'); updateStatus('提交失败,请手动提交'); } } async function waitForConfirmDialog() { return new Promise((resolve) => { let attempts = 0; const maxAttempts = 50; const checkInterval = setInterval(() => { attempts++; if (attempts >= maxAttempts) { clearInterval(checkInterval); logError('等待确认弹窗超时'); stopEvaluation(); resolve(); return; } const confirmBtn = document.querySelector('.bh-dialog-btn.bh-bg-primary'); if (confirmBtn && confirmBtn.textContent.trim() === '确认') { clearInterval(checkInterval); updateStatus('点击确认按钮...'); confirmBtn.click(); setTimeout(() => { updateStatus('等待页面刷新...'); setTimeout(() => { if (isListPage()) { updateStatus('页面已刷新,继续下一位...'); completedCount++; updateProgress(); setTimeout(() => { processListPage(); }, 1000); } else { updateStatus('等待中...'); } }, 3000); }, 500); } }, 200); setTimeout(() => { clearInterval(checkInterval); }, 10000); }); } async function processListPage() { const count = getPendingTeacherCount(); if (totalCount === 0) { totalCount = count; updateProgress(); } if (count === 0) { updateStatus('所有评教已完成!'); showNotification('评教完成', '所有老师评教已完成'); stopEvaluation(); return; } updateStatus(`发现 ${count} 位待评教老师,正在进入第一位...`); try { await sleep(1000); if (clickNextTeacher()) { await sleep(2000); if (isEvaluationPage()) { await processEvaluationPage(); } else { logError('无法进入评教页面'); stopEvaluation(); } } else { logError('无法点击进入评教页面'); updateStatus('无法进入评教页面'); stopEvaluation(); } } catch (error) { logError(`列表页面处理失败: ${error.message}`); stopEvaluation(); } } function stopEvaluation() { isProcessing = false; document.getElementById('start-eval-btn').disabled = false; document.getElementById('stop-eval-btn').disabled = true; updateStatus('已停止'); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function init() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createControlPanel); } else { createControlPanel(); } if (isEvaluationPage()) { updateStatus('检测到评教页面'); } else if (isListPage()) { const count = getPendingTeacherCount(); totalCount = count; updateProgress(); updateStatus(`检测到 ${count} 位待评教老师`); } else { updateStatus('⚠️ 请前往待评教列表页面'); } } init(); })();