NWAFU-评教

融合导航和自动填表功能。持续检测列表页和表单页。基本实现全自动评教。

// ==UserScript==
// @name         NWAFU-评教
// @namespace    http://tampermonkey.net/
// @version      3.71
// @description  融合导航和自动填表功能。持续检测列表页和表单页。基本实现全自动评教。
// @author       羊羊 & Gemini
// @match        https://newehall.nwafu.edu.cn/jwapp/sys/jwwspj/*default/index.do*
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';
    console.log("【NWAFU全自动评教脚本 V3.71 】脚本已启动");

    // --- 用户配置 (合并两者) ---
    // 填表相关 (来自脚本1)
    const COMMENT_TEXT = "无意见";
    const AUTO_SUBMIT = true;
    const AUTO_CONFIRM = true;
    const SUBMIT_DELAY_MS = 500;
    const CONFIRM_DELAY_MS = 1500;
    const MAX_CONFIRM_WAIT_TIME_MS = 10000;

    // 导航相关 (来自脚本2)
    const CHECK_INTERVAL_MS = 300; // 通用检查间隔
    const MAX_WAIT_TIME_MS = 10000; // 等待元素通用超时
    const TAB_SWITCH_DELAY_MS = 1500;
    const OBSERVER_DEBOUNCE_MS = 500; // Observer 防抖

    // *** 新增:导航后延迟 ***
    const NAVIGATION_COOLDOWN_MS = 5000; // 点击列表项进入表单后,导航逻辑暂停这么久 (毫秒)

    // --- 选择器常量 (合并两者) ---
    // 导航相关
    const LIST_PAGE_MARKER = 'div[title="结果性评教"]'; // 用于粗略判断是否在列表区
    const MAIN_CONTENT_AREA_SELECTOR = 'body';
    const RESULT_TAB_SELECTOR = 'div.bh-headerBar-nav-item[title="结果性评教"]';
    const PROCESS_TAB_SELECTOR = 'div.bh-headerBar-nav-item[title="过程评教"]';
    const ACTIVE_TAB_CLASS = 'bh-active';
    const EVALUATION_ITEM_CONTAINER_SELECTOR = '.bh-card.bh-card-lv1';
    const PENDING_TAG_SELECTOR = 'div.sc-panel-diagonalStrips-bar';
    const PENDING_TAG_TEXT = '未提交';
    // 填表相关
    const RADIO_INPUT_SELECTOR = 'input[type="radio"]:not([disabled])';
    const TEXTAREA_SELECTOR = 'textarea:not([disabled]):not([readonly])';
    const SUBMIT_BUTTON_SELECTOR = 'a[data-action="提交"]:not([disabled])';
    const CONFIRM_BUTTON_SELECTOR = 'a.bh-dialog-btn.bh-bg-primary.bh-color-primary-5';

    // --- 状态变量 ---
    let observerDebounceTimer = null;
    let confirmWaitTimeout = null; // 用于等待确认按钮
    let isFillingForm = false;     // 标记是否正在执行填表操作 (来自脚本1的isEvaluating)
    let lastNavigationClickTime = 0; // 记录上次点击列表项的时间戳

    // --- 警告 ---
    if (AUTO_SUBMIT) console.warn("【NWAFU全自动评教脚本】警告:已启用自动提交功能!");
    if (AUTO_CONFIRM) console.warn("【NWAFU全自动评教脚本】警告:已启用自动点击“确认”功能!延迟 " + (CONFIRM_DELAY_MS / 1000) + " 秒。");

    // --- 辅助函数:显示消息给用户 (选用脚本1的版本) ---
    function displayMessage(message, type = 'info', duration = 5000) {
        console[type === 'error' ? 'error' : (type === 'warning' ? 'warn' : 'log')](message);
        const messageBoxId = 'nwafu-evaluation-script-message-merged';
        let messageBox = document.getElementById(messageBoxId);
        if (!messageBox && document.body) {
            messageBox = document.createElement('div');
            messageBox.id = messageBoxId;
            Object.assign(messageBox.style, {
                position: 'fixed',
                top: '15px',
                right: '15px',
                padding: '12px 18px',
                backgroundColor: '#fff',
                borderLeft: '5px solid #ccc',
                zIndex: '10001',
                borderRadius: '4px',
                fontSize: '14px',
                color: '#333',
                maxWidth: '350px',
                wordBreak: 'break-word',
                boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
                transition: 'opacity 0.5s ease-in-out, transform 0.3s ease-out',
                opacity: '0',
                transform: 'translateX(100%)',
                fontFamily: 'sans-serif',
                lineHeight: '1.5'
            });
            document.body.appendChild(messageBox);
        } else if (!document.body) {
            return;
        }

        let borderColor = '#4CAF50'; // success (default info)
        if (type === 'info') borderColor = '#2196F3';
        if (type === 'warning') borderColor = '#ff9800';
        if (type === 'error') borderColor = '#f44336';

        if (messageBox) {
            messageBox.style.borderLeftColor = borderColor;
            messageBox.innerHTML = message.replace(/\n/g, '<br>'); // Use innerHTML for line breaks
            messageBox.style.display = 'block';

            // Fade in animation
            setTimeout(() => {
                if (messageBox) {
                    messageBox.style.opacity = '1';
                    messageBox.style.transform = 'translateX(0)';
                }
            }, 50);

            // Auto hide logic
            if (messageBox.hideTimeout) clearTimeout(messageBox.hideTimeout);

            let hideDelay = duration;
            if (type === 'error') hideDelay = 15000;
            else if (type === 'warning') hideDelay = 10000;
            else if (type === 'success') hideDelay = 6000;

            if (hideDelay > 0) {
                messageBox.hideTimeout = setTimeout(() => {
                    if (messageBox) {
                        messageBox.style.opacity = '0';
                        messageBox.style.transform = 'translateX(100%)';
                        // Remove from DOM after transition
                        setTimeout(() => {
                            if (messageBox && messageBox.style.opacity === '0') {
                                messageBox.remove();
                            }
                        }, 500);
                    }
                }, hideDelay);
            } else { // duration <= 0 means persistent message
                messageBox.hideTimeout = null;
            }
        }
    }

    // --- 辅助函数:等待元素加载 (来自脚本2) ---
    function waitForElement(selector, timeout = MAX_WAIT_TIME_MS, baseElement = document) {
        return new Promise((resolve, reject) => {
            let element = baseElement.querySelector(selector);
            if (element && element.offsetParent !== null) { // Check visibility too
                resolve(element);
                return;
            }

            let intervalId = null;
            let timeoutId = null;

            const clearTimers = () => {
                clearInterval(intervalId);
                clearTimeout(timeoutId);
            };

            const check = () => {
                element = baseElement.querySelector(selector);
                if (element && element.offsetParent !== null) { // Check visibility
                    clearTimers();
                    resolve(element);
                }
            };

            intervalId = setInterval(check, CHECK_INTERVAL_MS);

            timeoutId = setTimeout(() => {
                clearTimers();
                console.warn(`【NWAFU全自动评教脚本】等待元素 ${selector} 超时 (${timeout}ms)`);
                reject(new Error(`Element ${selector} not found or not visible within ${timeout}ms`));
            }, timeout);

            check(); // Initial check
        });
    }


    // --- 填表逻辑 (来自脚本1,略作修改以使用 isFillingForm 状态) ---
    function containsEvaluationForm() { // 判断是否是“可填写”的表单页
        const radios = document.querySelectorAll(RADIO_INPUT_SELECTOR);
        const submitButton = document.querySelector(SUBMIT_BUTTON_SELECTOR);
        const isSubmitButtonVisible = !!submitButton && submitButton.offsetParent !== null;
        // 简单判断:有单选按钮 且 提交按钮可见
        return radios.length > 0 && isSubmitButtonVisible;
    }

    function selectFirstRadioOption() {
        console.log("【NWAFU全自动评教脚本】步骤 1: 尝试选择“完全赞同”...");
        try {
            const allRadios = document.querySelectorAll(RADIO_INPUT_SELECTOR);
            if (allRadios.length === 0) {
                console.log("【NWAFU全自动评教脚本】未找到任何可用的单选按钮。");
                return false;
            }
            const radioGroups = {};
            allRadios.forEach(radio => {
                if (radio.offsetParent === null) return; // Skip invisible
                const name = radio.name;
                if (!name) return; // Skip radios without name (shouldn't happen in groups)
                if (!radioGroups[name]) {
                    radioGroups[name] = [];
                }
                radioGroups[name].push(radio);
            });

            const groupNames = Object.keys(radioGroups);
            if (groupNames.length === 0) {
                console.log("【NWAFU全自动评教脚本】未找到任何可见且可用的单选按钮组。");
                return false;
            }
            console.log(`【NWAFU全自动评教脚本】找到 ${groupNames.length} 个可见且可用的单选题组。`);

            let selectedCount = 0;
            let groupsProcessed = 0;
            for (const name of groupNames) {
                groupsProcessed++;
                // Only select if no option in the group is already checked
                const isAlreadySelected = radioGroups[name].some(radio => radio.checked);
                if (isAlreadySelected) {
                    selectedCount++;
                    continue;
                }

                const firstOption = radioGroups[name][0]; // Get the first radio in the group
                if (firstOption) {
                    firstOption.checked = true;
                    // Dispatch events to ensure frameworks recognize the change
                    firstOption.dispatchEvent(new Event('change', { bubbles: true }));
                    firstOption.dispatchEvent(new Event('input', { bubbles: true }));
                    selectedCount++;
                } else {
                    console.warn(`【NWAFU全自动评教脚本】单选题组 "${name}" 没有找到可用选项(异常情况)。`);
                }
            }

            if (selectedCount === 0 && groupsProcessed > 0) {
                console.warn("【NWAFU全自动评教脚本】未能选择任何单选按钮,可能是元素尚未完全加载或已被处理。");
                return false;
            }

            console.log(`【NWAFU全自动评教脚本】“完全赞同”选项选择完成,处理了 ${selectedCount} / ${groupsProcessed} 个组。`);
            return true; // Indicate success

        } catch (error) {
            console.error("【NWAFU全自动评教脚本】选择“完全赞同”时出错:", error);
            displayMessage("选择选项时出错,请检查控制台。", 'error');
            return false; // Indicate failure
        }
    }

    function fillTextBoxes() {
        console.log(`【NWAFU全自动评教脚本】步骤 2: 尝试填写评语:“${COMMENT_TEXT}”...`);
        try {
            const textAreasNodeList = document.querySelectorAll(TEXTAREA_SELECTOR); // Keep original NodeList query
            if (textAreasNodeList.length === 0) {
                console.log("【NWAFU全自动评教脚本】未找到需要填写的文本框 (textarea)。");
                return true; // Nothing to fill is considered success for this step
            }

            const textAreas = Array.from(textAreasNodeList); // Convert to Array
            console.log(`【NWAFU全自动评教脚本】找到 ${textAreas.length} 个可编辑文本框。`);

            let filledCount = 0;
            let visibleCount = 0; // Count visible ones separately

            textAreas.forEach((textarea) => {
                if (textarea.offsetParent !== null) { // Check visibility
                    visibleCount++; // Increment visible count
                    if (textarea.value.trim() === '') { // Only fill if empty
                        textarea.value = COMMENT_TEXT;
                        // Dispatch events
                        textarea.dispatchEvent(new Event('input', { bubbles: true }));
                        textarea.dispatchEvent(new Event('change', { bubbles: true }));
                        filledCount++;
                    } else {
                        // Textarea already has content, count as 'processed' towards filled count
                        filledCount++;
                    }
                }
            });

            console.log(`[DEBUG] fillTextBoxes: filledCount = ${filledCount}, visibleCount = ${visibleCount}`);
            if (filledCount < visibleCount) {
                console.warn(`【NWAFU全自动评教脚本】可能部分可见文本框未能处理(已处理 ${filledCount} / ${visibleCount} 可见文本框)。`);
            } else {
                console.log(`【NWAFU全自动评教脚本】评语填写/检查完成,处理了 ${filledCount} 个可见文本框。`);
            }
            return true; // Return true even if some were pre-filled or not visible

        } catch (error) {
            console.error("【NWAFU全自动评教脚本】填写评语时发生内部错误:", error);
            displayMessage("填写评语时发生内部错误,请检查控制台。", 'error');
            return false; // Indicate failure
        }
    }

    async function clickSubmitButton_Form() {
        console.log("【NWAFU全自动评教脚本】步骤 3: 尝试查找并点击“提交”按钮...");
        try {
            // Wait for the submit button to be clickable and visible
            const submitButton = await waitForElement(SUBMIT_BUTTON_SELECTOR, 5000);

            console.log(`【NWAFU全自动评教脚本】找到可见的“提交”按钮,将在 ${SUBMIT_DELAY_MS} 毫秒后点击...`);
            displayMessage(`填写完成,${SUBMIT_DELAY_MS}ms后自动提交...`, 'info', SUBMIT_DELAY_MS + 500);

            await new Promise(resolve => setTimeout(resolve, SUBMIT_DELAY_MS)); // Wait before clicking

            // Re-check button just before clicking, in case state changed
            const currentSubmitButton = document.querySelector(SUBMIT_BUTTON_SELECTOR);
            if (currentSubmitButton && currentSubmitButton.offsetParent !== null) {
                currentSubmitButton.click();
                console.log("【NWAFU全自动评教脚本】“提交”按钮已点击。");
                return true; // Indicate submit was clicked
            } else {
                console.error("【NWAFU全自动评教脚本】错误:提交按钮在延迟后消失或被禁用。提交失败。");
                displayMessage("错误:提交按钮状态变化,无法点击!请手动提交。", 'error', 10000);
                return false; // Indicate failure
            }
        } catch (error) {
            console.error(`【NWAFU全自动评教脚本】查找或点击“提交”按钮时发生错误 (选择器: "${SUBMIT_BUTTON_SELECTOR}"):`, error);
            displayMessage(`错误:未能找到或点击“提交”按钮!请手动提交。\n${error.message}`, 'error', 10000);
            return false; // Indicate failure
        }
    }

    function clickConfirmationButton_Form() {
        console.log("【NWAFU全自动评教脚本】步骤 4: 等待并点击确认对话框...");
        let startTime = Date.now();
        clearTimeout(confirmWaitTimeout); // Clear previous timer if any

        function checkConfirmationButton() {
            if (Date.now() - startTime > MAX_CONFIRM_WAIT_TIME_MS) {
                console.error(`【NWAFU全自动评教脚本】错误:等待“确认”按钮加载超时 (${MAX_CONFIRM_WAIT_TIME_MS}ms)。`);
                displayMessage(`错误:等待“确认”按钮超时。请手动确认或刷新。`, 'error', 15000);
                isFillingForm = false; // Reset state on timeout
                return;
            }

            const confirmButton = document.querySelector(CONFIRM_BUTTON_SELECTOR);

            if (confirmButton && confirmButton.offsetParent !== null) { // Found and visible
                console.log(`【NWAFU全自动评教脚本】找到可见的“确认”按钮,将在 ${CONFIRM_DELAY_MS} 毫秒后点击...`);
                displayMessage(`找到确认按钮,${CONFIRM_DELAY_MS / 1000} 秒后点击...`, 'info', CONFIRM_DELAY_MS + 500);

                setTimeout(() => {
                    try {
                        // Re-check button just before clicking
                        const currentConfirmButton = document.querySelector(CONFIRM_BUTTON_SELECTOR);
                        if (currentConfirmButton && currentConfirmButton.offsetParent !== null) {
                            currentConfirmButton.click();
                            console.log("【NWAFU全自动评教脚本】“确认”按钮已点击。评教完成!");
                            displayMessage("评教确认完成!页面即将刷新或跳转...", 'success', 5000);
                        } else {
                            console.error("【NWAFU全自动评教脚本】错误:确认按钮在延迟后消失。确认失败。");
                            displayMessage("错误:确认按钮状态变化,无法点击!请手动处理。", 'error', 10000);
                        }
                    } catch (error) {
                        console.error("【NWAFU全自动评教脚本】点击“确认”按钮时发生错误:", error);
                        displayMessage(`点击“确认”按钮时发生错误,请手动处理。\n${error.message}`, 'error', 10000);
                    } finally {
                        // 无论成功失败,完成确认尝试后都重置状态
                        isFillingForm = false;
                        console.log("[DEBUG] isFillingForm set to false after confirmation attempt.");
                    }
                }, CONFIRM_DELAY_MS);

            } else {
                // Confirm button not found or not visible, wait and check again
                confirmWaitTimeout = setTimeout(checkConfirmationButton, CHECK_INTERVAL_MS * 2); // Check less frequently for confirm dialog
            }
        }

        checkConfirmationButton(); // Start checking
    }

    async function runAutoEvaluation() {
        if (isFillingForm) return; // 如果已在处理,则退出

        if (containsEvaluationForm()) {
            isFillingForm = true; // 设置处理中标志
            console.log("【NWAFU全自动评教脚本 - 填表】检测到评教表单,开始自动处理...");
            displayMessage("检测到评教表单,开始自动处理...", 'info', 3000);

            const step1Success = selectFirstRadioOption();
            const step2Success = fillTextBoxes();

            if (step1Success === false || step2Success === false) {
                console.error("【NWAFU全自动评教脚本 - 填表】填写步骤中遇到问题,自动提交已取消。");
                displayMessage("填写步骤遇到问题,自动提交已取消。请手动检查。", 'warning', 10000);
                isFillingForm = false; // 重置状态
                return;
            }

            if (AUTO_SUBMIT) {
                const submitted = await clickSubmitButton_Form();
                if (!submitted) {
                    isFillingForm = false; // 重置状态
                    return; // Stop processing
                }

                if (AUTO_CONFIRM) {
                    clickConfirmationButton_Form(); // 确认函数内部会重置 isFillingForm
                } else {
                    console.log("【NWAFU全自动评教脚本 - 填表】自动确认已禁用。请手动确认。");
                    displayMessage("填写完成,提交按钮已点击。请手动确认。", 'info', false); // Persistent message
                    isFillingForm = false; // 重置状态
                }
            } else {
                // Auto-submit disabled
                console.log("【NWAFU全自动评教脚本 - 填表】自动填写完成。自动提交已禁用。");
                displayMessage("自动填写完成。请检查并手动提交。", 'info', false); // Persistent message
                isFillingForm = false; // Reset state as manual action needed
            }
        }
        // else { console.log("【NWAFU全自动评教脚本 - 填表】未检测到可执行的评教表单。"); }
    }


    // --- 导航逻辑 (来自脚本2, 略作修改以配合延迟) ---
    function findAndClickNextEvaluation_Nav() {
        console.log(`【NWAFU全自动评教脚本 - 导航】查找 "${PENDING_TAG_TEXT}" 标签...`);
        try {
            const containers = document.querySelectorAll(EVALUATION_ITEM_CONTAINER_SELECTOR);
            if (containers.length === 0) {
                console.log(`【NWAFU全自动评教脚本 - 导航】未找到项目容器。`);
                return false; // No items found
            }
            // console.log(`【NWAFU全自动评教脚本 - 导航】找到 ${containers.length} 个项目容器。`); // Less verbose

            for (const container of containers) {
                const pendingTag = container.querySelector(PENDING_TAG_SELECTOR);
                if (pendingTag && pendingTag.textContent?.trim() === PENDING_TAG_TEXT) {
                    if (pendingTag.offsetParent !== null) { // Check visibility
                        console.log(`【NWAFU全自动评教脚本 - 导航】>> 找到可见的 "${PENDING_TAG_TEXT}" 标签,准备点击...`);
                        displayMessage(`找到 "${PENDING_TAG_TEXT}" 项目,正在进入...`, 'info', 2000);
                        try {
                            const clickableElement = pendingTag.closest('a') || pendingTag; // Try to find a parent link or click the tag itself
                            clickableElement.click();
                            // *** 关键:记录点击时间 ***
                            lastNavigationClickTime = Date.now();
                            console.log(`【NWAFU全自动评教脚本 - 导航】已点击 "${PENDING_TAG_TEXT}",导航冷却开始 (${NAVIGATION_COOLDOWN_MS}ms)。`);
                            return true; // Click attempted, stop searching
                        } catch (clickError) {
                            console.error(`【NWAFU全自动评教脚本 - 导航】点击 "${PENDING_TAG_TEXT}" 出错:`, clickError);
                            displayMessage(`错误:点击 "${PENDING_TAG_TEXT}" 失败。`, 'error', false);
                            return false; // Indicate failure
                        }
                    }
                }
            }

            // console.log(`【NWAFU全自动评教脚本 - 导航】未找到可见的 "${PENDING_TAG_TEXT}" 标签。`);
            return false; // None found

        } catch (error) {
            console.error("【NWAFU全自动评教脚本 - 导航】查找评教项目时出错:", error);
            displayMessage("查找评教项目出错。", 'error');
            return false;
        }
    }

    async function runNavigationLogic() {
        // *** 关键:检查冷却时间 ***
        const now = Date.now();
        if (now - lastNavigationClickTime < NAVIGATION_COOLDOWN_MS) {
            console.log(`【NWAFU全自动评教脚本 - 导航】导航功能冷却中,剩余 ${Math.round((NAVIGATION_COOLDOWN_MS - (now - lastNavigationClickTime)) / 1000)} 秒...`);
            return; // 冷却中,不执行
        }

        // 粗略判断是否在列表页区域
        if (!document.querySelector(LIST_PAGE_MARKER)) {
            // console.log("【NWAFU全自动评教脚本 - 导航】未检测到列表页标记,跳过导航逻辑。");
            return;
        }

        console.log("【NWAFU全自动评教脚本 - 导航】开始处理列表页导航...");

        if (findAndClickNextEvaluation_Nav()) {
            return; // 找到并点击了,等待跳转,导航逻辑暂停
        }

        // 如果没找到,尝试切换 Tab
        console.log(`【NWAFU全自动评教脚本 - 导航】当前Tab无 "${PENDING_TAG_TEXT}",检查并切换Tab...`);
        try {
            const resultTab = document.querySelector(RESULT_TAB_SELECTOR);
            const processTab = document.querySelector(PROCESS_TAB_SELECTOR);
            if (resultTab && processTab) {
                if (resultTab.classList.contains(ACTIVE_TAB_CLASS)) {
                    console.log(`【NWAFU全自动评教脚本 - 导航】切换到过程性...`);
                    processTab.click();
                    lastNavigationClickTime = Date.now(); // 切换Tab也视为一次导航动作,启动冷却
                    console.log(`【NWAFU全自动评教脚本 - 导航】已点击切换Tab,导航冷却开始 (${NAVIGATION_COOLDOWN_MS}ms)。`);
                } else if (processTab.classList.contains(ACTIVE_TAB_CLASS)) {
                    console.log(`【NWAFU全自动评教脚本 - 导航】过程性列表也无未提交。`);
                    displayMessage("所有Tab似乎都已检查完毕。", 'success', 10000);
                    // 可选:增加更长的冷却时间,避免频繁检查已完成的列表
                    // lastNavigationClickTime = Date.now() + 60000; // 冷却1分钟
                }
            } else {
                console.warn("【NWAFU全自动评教脚本 - 导航】无法找到Tab元素。");
            }
        } catch (error) {
            console.error("【NWAFU全自动评教脚本 - 导航】处理Tab时出错:", error);
        }
    }


    // --- 主执行逻辑 (简化版,同时尝试两种逻辑) ---
    function runCombinedLogic() {
        console.log("--- 【NWAFU全自动评教脚本 V3.7】开始执行检查 ---");

        // 清理旧消息
        const oldMessageBox = document.getElementById('nwafu-evaluation-script-message-merged');
        if (oldMessageBox) { clearTimeout(oldMessageBox.hideTimeout); oldMessageBox.remove(); }

        // 1. 尝试执行自动填表逻辑 (它内部有 isFillingForm 状态控制)
        runAutoEvaluation();

        // 2. 尝试执行导航逻辑 (它内部有冷却时间控制)
        runNavigationLogic();

        console.log("--- 【NWAFU全自动评教脚本 V3.7】检查执行完毕 ---");
    }

    // --- MutationObserver 设置 ---
    const observerCallback = function(mutationsList, observer) {
        let relevantChange = false;
        for (const mutation of mutationsList) {
            if (mutation.type === 'childList' && (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0)) {
                relevantChange = true;
                break;
            }
        }
        if (!relevantChange) return;

        clearTimeout(observerDebounceTimer);
        observerDebounceTimer = setTimeout(() => {
            console.log("【NWAFU全自动评教脚本 V3.7】MutationObserver 检测到变化,准备执行...");
            if (document.readyState === 'complete' || document.readyState === 'interactive') {
                runCombinedLogic(); // 直接运行合并逻辑
            } else {
                console.log("[DEBUG] Observer fired but document not ready, delaying execution slightly.");
                setTimeout(runCombinedLogic, 150);
            }
        }, OBSERVER_DEBOUNCE_MS);
    };

    // --- 启动脚本和观察者 ---
    let initialized = false;
    function initialize() {
        if (initialized) return;
        initialized = true;
        console.log("【NWAFU全自动评教脚本 V3.7】初始化...");
        displayMessage("全自动评教脚本 (模拟并发+延迟) V3.7 已启动", 'success', 4000);

        // 初始运行
        setTimeout(runCombinedLogic, 500);

        // 设置观察者
        const targetNode = document.querySelector(MAIN_CONTENT_AREA_SELECTOR) || document.body;
        if (targetNode) {
            const config = { childList: true, subtree: true };
            const observer = new MutationObserver(observerCallback);
            try {
                observer.observe(targetNode, config);
                console.log(`【NWAFU全自动评教脚本 V3.7】MutationObserver 已启动,监听目标:`, targetNode);
            } catch (e) {
                console.error("【NWAFU全自动评教脚本】启动 MutationObserver 失败:", e);
                displayMessage("错误:无法启动页面变化监听器!", "error", false);
            }
        } else {
            console.error("【NWAFU全自动评教脚本】错误:无法找到用于 MutationObserver 的目标节点!");
            displayMessage("错误:无法找到监听目标!", "error", false);
        }
    }

    // --- 脚本启动入口 ---
    if (document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll)) {
        setTimeout(initialize, 300);
    } else {
        document.addEventListener("DOMContentLoaded", () => setTimeout(initialize, 300));
        window.addEventListener("load", () => setTimeout(initialize, 300)); // Add load listener as fallback
    }

})();