Greasy Fork 支持简体中文。

重庆高等教育智慧教育平台学习助手 || cqooc重庆高等教育智慧教育平台学习助手 || www.cqooc.com

1.看说明就行了。2.反对任何形式牟利,祝各位同学学有所成。3.更新了作业测验作答

// ==UserScript==
// @name         重庆高等教育智慧教育平台学习助手 || cqooc重庆高等教育智慧教育平台学习助手 || www.cqooc.com
// @namespace    http://tampermonkey.net/
// @version      3.2
// @description  1.看说明就行了。2.反对任何形式牟利,祝各位同学学有所成。3.更新了作业测验作答
// @author       Abstract
// @include      https://*.cqooc.com/*
// @grant        none
// @run-at       document-end
// @require      https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';



    let currentTimeout = null;
    let currentInterval = null;
    let pageInitialized = false;
    let pptTimeoutId = null;

    let currentPlayingVideo = null;
    let coursewareQueue = [];
    let isProcessing = false;

    let pptTaskId = null;

    let currentQueueName = null;
    let isQueueProcessing = false;


    const completionStatuses = {
        '未完成': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAACklpQ0NQc1JHQiBJRUM2MTk2Ni0yLjEAAEiJnVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/stRzjPAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAJcEhZcwAACxMAAAsTAQCanBgAAADXSURBVBiVjZA7agJRAEXPewHRZViMC5AYZGxN5Sc7mPRJESJoO2JjYdDO2YidWEgI5qMbkIC7mFFHvTYTCBohp7yc5h4jCYBcu3QHPBljbgAkfQL9ZfttRDLg+G63Fnh6/f5QvIsV72JNlzNVh54c3+1IAsd36/XgXuEm0inhJlIt8OT4bsUCjdbtI5lUmlMyqTTN8gPAs72ytlDM5s+kH4rZPMaYawvoogUkX7H7w2E+Wy0uiu+rBZLmFuj3xkOi7fpMCrcRL5MAYPDvPOaP4IWk79fv4Eft841qprSDGwAAAABJRU5ErkJggg==',
        '半完成': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAbVJREFUSEu9ls8rRFEUx7/nzsjvjWQxSSTPJE1Zv0nUjEiIhRQbxQKTUiSr914pK6mJFWUjlqL8ysbCrJWVIWUh/wBF4R3d18w0zMwzi7nztu/7zuee7zn3nEdweQJGV/2H+BqCzf0gNAPwJeQvYDxC0EmZ7T26ta6ec4WhbC9aDd3HBIsZkwB73A4B0DcRdolhxK3Yy19tBqDV0AcZ2GNwtVd4EPJ3IuzvRLvPj7rqWnSshbPyCPRKwETcih2nC34BWszgPGBvgCFk0OWeOTTU1P8KqJl67oQINiAWHszraFKUAsiT28SHBBKLoRlM6+NZA7kC5BcEWzANJzNxAI7nwJ20ZSk8mzO41P4LcBiOXX5ZEwegmfo2M09JW7bG1lxrmg/ASYRo596MTZNsxXd8PnmF8JxH9jM8/0vLFyC7qxwljaRZwTm27c3etm5ER1fdOzJPi1IFFiJCmqGfMrhvfcTAQKCnsADQGWmmHmdm7SJygKbahsICiO4l4JWZq25WLlFZWlFowFtRAIotUl5k1W2q/KIpHxVFGXYJiLpxnbxdShdOEqJ0ZaZB1C399GFUiN+WH16q+w/WuLNCAAAAAElFTkSuQmCC',
        '已完成': 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAfhJREFUSEu9lj1oE2EYx//PqaDYDJHaQlCoH7k4dVYuUMFFERSHQIeCUcxiih/QpXS4u9Gp9MNJwSWC4CAKKgiClgSLg4hkMIkBISFrhwhKPu4p7zWXz7vLXWjMmPd5/r/3+XyP4PKbVS+e+Cc1rsPgqyCcARBqmVfAKEKit4eNg69/6J/KTjJkdxBRlRATdGbcAviA2yUAahLhGTHUnJ6p9NsOACKqco2BFIMD7sK9pwSqErCQ0zNvuk96AGEteg8wVsGQ/Ii3bQkGID0saOl16782QNzcIH41snhH0ZCYbliRmAAz58BPv2lxLqyZrnOiJiZA1pQnzHxnpLQ4OBHR07yWSZBoxb+o/x7eLX7x1DyCQzMk69EkG8amX3cv9iRJiySryjsGX/Hi0G8zHZhEeOo00sWvtu4Eek+ypuSYWfYLOHv8FFLxDRw7GsSltRhKOwMzBiLKC0CVmSf8ALrFPxe+IPF8yT4Coj+ugNsX5vGtlMX3crYt0C9+98Uy6s26K8A2RSeDIXy8/xK1Rg1CZOvXNvyIC+JeilyKvHL5AW6ej5mQRx8eIzkXN3Mu0uJ2885QiyIPaVMLYjl5FTcjEG3qZdAsiB9xscbNQfO6KkRN7FrRcR9Zq+K/LLsWZHzr2gpzrA+OBRnrk9kFGd+j390V+/HZsgvSIhcecicecAAAAABJRU5ErkJggg=='
    };

    const MAIN_PAGE_HOST = 'www.cqooc.com';
    const IFRAME_PAGE_HOST = 'preview.cqooc.com';

    let isProcessingQueue = false;

    let coursewareQueues = {
        '默认未完成队列': {
            items: [],
            interval: 240000
        }
    };


    const categoryKeywords = {
        '测验': ['测验', '测试'],
        '课件': ['课件', '小节', '视频'],
        '作业': ['作业'],
        '讨论': ['讨论', '答疑'],
        '考试': ['考试', '期末测试', '补考'],
        '其他': []
    };

  
    let processedItems = new Set();

 
    function simulateClick(element) {
        if (!element) return;
        const event = new MouseEvent('click', {
            view: window,
            bubbles: true,
            cancelable: true
        });
        element.dispatchEvent(event);
    }

  
    async function expandAllParentsAsync(element) {
        const parents = [];
        let parent = element.parentElement;

        while (parent && parent !== document.body) {
            if (parent.classList.contains('second-level-inner-box') || parent.classList.contains('first-level-inner-box')) {
                parents.push(parent);
            }
            parent = parent.parentElement;
        }

        parents.reverse();

        for (const parent of parents) {
            const toggleButton = parent.previousElementSibling && parent.previousElementSibling.querySelector('.right-icon > i.anticon-down');
            if (toggleButton) {
                const innerBox = parent;
                const height = window.getComputedStyle(innerBox).height;
                if (height === '0px') {
                    simulateClick(toggleButton);
                    await new Promise(resolve => setTimeout(resolve, 500));
                }
            }
        }
    }

    function waitForElement(selector, timeout) {
        return new Promise(resolve => {
            const startTime = Date.now();

            const interval = setInterval(() => {
                const element = document.querySelector(selector);
                if (element) {
                    clearInterval(interval);
                    resolve(element);
                } else if (Date.now() - startTime > timeout) {
                    clearInterval(interval);
                    resolve(null);
                }
            }, 100);
        });
    }

    async function jumpToContentItem(originalElement) {
        return new Promise(async (resolve, reject) => {
            try {
                let targetElement = originalElement;
                if (!document.body.contains(originalElement)) {
                    const title = originalElement.querySelector('p.title')?.textContent.trim();
                    if (title) {
                        targetElement = Array.from(document.querySelectorAll('.third-level-inner-box'))
                            .find(el => el.querySelector('p.title')?.textContent.trim() === title);
                    }
                    if (!targetElement) {
                        throw new Error('找不到目标元素');
                    }
                }

                await expandAllParentsAsync(targetElement);
                const clickable = targetElement.querySelector('a') ||
                      targetElement.querySelector('p.title') ||
                      targetElement;
                if (!clickable) {
                    throw new Error('未找到可点击的元素');
                }

                clickable.scrollIntoView({ behavior: 'smooth', block: 'center' });
                setTimeout(() => {
                    simulateClick(clickable);
                    resolve();
                }, 500);

            } catch (error) {
                console.error('跳转失败:', error);
                reject(error);
            }
        });
    }


    async function performBatchAutoReply(data, progressLabel) {
        let repliedCount = 0;
        for (const item of data.items) {
            try {
                await performAutoReply(item);
                repliedCount++;
                updateReplyProgress(data, progressLabel, repliedCount);
            } catch (error) {
                console.error('一键回复失败:', error);
            }
        }
    }


    async function performAutoReply(itemData) {
        try {
            await jumpToContentItem(itemData.originalElement);
            const discussionArea = await waitForElement('.course-courseQaDiscussion-qa', 5000);
            if (!discussionArea) return;

            const replyButton = discussionArea.querySelector('.conv-option .reply');
            if (!replyButton) return;

            replyButton.click();

            const replyInput = await waitForElement('.course-courseQaDiscussion-reply textarea.ant-input', 2000);
            const submitButton = await waitForElement('.course-courseQaDiscussion-reply .ant-btn-primary', 2000);
            const firstReply = discussionArea.querySelector('.conv-subtitle');

            if (replyInput && submitButton && firstReply) {
                replyInput.value = firstReply.textContent.trim();
                replyInput.dispatchEvent(new Event('input', { bubbles: true }));
                submitButton.click();


                itemData.replyStatus = '已回复';
                itemData.replyStatusElement.textContent = '已回复';
                itemData.replyStatusElement.style.color = 'green';

                console.log('自动回复完成');
            }
        } catch (error) {
            console.error('自动回复失败:', error);
        }
    }

    function updateReplyProgress(data, progressLabel, repliedCount = null) {
        if (repliedCount === null) {
            repliedCount = data.items.filter(item => item.replyStatus === '已回复').length;
        }
        progressLabel.textContent = `已回复:${repliedCount}/${data.items.length}`;
    }

    async function collectTestAttempts(data, progressLabel) {
        let processedCount = 0;
        for (const itemData of data.items) {
            try {
                await jumpToContentItem(itemData.originalElement);
                const attemptInfo = await getTestAttemptInfo();
                const timeInfo = await getTestTimeInfo();

                updateTestItemWithAttemptInfo(itemData, attemptInfo, timeInfo);

                processedCount++;
                progressLabel.textContent = `已获取:${processedCount}/${data.items.length}`;
                await new Promise(resolve => setTimeout(resolve, 500));

            } catch (error) {
                console.error('获取测验信息失败:', error);
            }
        }
    }

    async function getTestAttemptInfo() {
        return new Promise((resolve, reject) => {
            const timeout = 3000;
            const startTime = Date.now();

            const interval = setInterval(() => {
                const attemptElements = document.querySelectorAll('.list-content-text p');
                for (const p of attemptElements) {
                    if (p.textContent.includes('已作答/可作答次数')) {
                        const span = p.querySelector('span');
                        if (span) {
                            clearInterval(interval);
                            resolve(span.textContent.trim());
                            return;
                        }
                    }
                }

                if (Date.now() - startTime > timeout) {
                    clearInterval(interval);
                    reject('获取作答信息超时');
                }
            }, 100);
        });
    }

    async function getTestTimeInfo() {
        return new Promise((resolve, reject) => {
            const timeout = 3000;
            const startTime = Date.now();

            const interval = setInterval(() => {
                const timeElements = document.querySelectorAll('.list-content-text p');
                for (const p of timeElements) {
                    if (p.textContent.includes('开始至截止时间:')) {
                        const span = p.querySelector('span');
                        if (span) {
                            clearInterval(interval);
                            resolve(span.textContent.trim());
                            return;
                        }
                    }
                }

                if (Date.now() - startTime > timeout) {
                    clearInterval(interval);
                    reject('获取开始至截止时间超时');
                }
            }, 100);
        });
    }

    function updateTestItemWithAttemptInfo(itemData, attemptInfo, timeInfo) {
        if (itemData.taskNameElement) {
            const infoContainer = document.createElement('div');
            infoContainer.style.display = 'flex';
            infoContainer.style.flexDirection = 'column';
            infoContainer.style.marginLeft = '10px';

            const attemptLabel = document.createElement('span');
            attemptLabel.textContent = `作答信息:${attemptInfo}`;
            attemptLabel.style.color = 'blue';
            infoContainer.appendChild(attemptLabel);

            const timeLabel = document.createElement('span');
            timeLabel.textContent = `时间:${timeInfo}`;
            timeLabel.style.color = 'green';
            infoContainer.appendChild(timeLabel);

            itemData.taskNameElement.parentElement.appendChild(infoContainer);
        }
    }

    async function collectAssignmentInfo(data, progressLabel) {
        let processedCount = 0;
        for (const itemData of data.items) {
            try {
                await jumpToContentItem(itemData.originalElement);
                const attemptInfo = await getAssignmentAttemptInfo();
                const timeInfo = await getAssignmentTimeInfo();

                updateAssignmentItemWithInfo(itemData, attemptInfo, timeInfo);

                processedCount++;
                progressLabel.textContent = `已获取:${processedCount}/${data.items.length}`;
                await new Promise(resolve => setTimeout(resolve, 100));
            } catch (error) {
                console.error('获取作业信息失败:', error);
            }
        }
    }

async function getAssignmentAttemptInfo() {
    return new Promise((resolve, reject) => {
        const timeout = 3000;
        const startTime = Date.now();

        const interval = setInterval(() => {
            const attemptElement = Array.from(document.querySelectorAll('.list-content-text p'))
                .find(p => p.textContent.includes('已作答/可作答次数'))
                ?.querySelector('span');

            if (attemptElement) {
                clearInterval(interval);
                resolve(attemptElement.textContent.trim());
                return;
            }

            if (Date.now() - startTime > timeout) {
                clearInterval(interval);
                reject('获取作答次数超时');
            }
        }, 100);
    });
}


    async function getAssignmentTimeInfo() {
        return new Promise((resolve, reject) => {
            const timeout = 3000;
            const startTime = Date.now();

            const interval = setInterval(() => {
                const timeElement = Array.from(document.querySelectorAll('.list-content-text p'))
                .find(p => p.textContent.includes('开始至截止时间:'))?.querySelector('span');

                if (timeElement) {
                    clearInterval(interval);
                    resolve(timeElement.textContent.trim());
                }

                if (Date.now() - startTime > timeout) {
                    clearInterval(interval);
                    reject('获取开始至截止时间超时');
                }
            }, 100);
        });
    }

    function updateAssignmentItemWithInfo(itemData, attemptInfo, timeInfo) {
        if (itemData.taskNameElement) {
            const infoContainer = document.createElement('div');
            infoContainer.style.display = 'flex';
            infoContainer.style.flexDirection = 'column';
            infoContainer.style.marginLeft = '10px';

            const attemptLabel = document.createElement('span');
            attemptLabel.textContent = `作答信息:${attemptInfo}`;
            attemptLabel.style.color = 'blue';
            infoContainer.appendChild(attemptLabel);

            const timeLabel = document.createElement('span');
            timeLabel.textContent = `时间:${timeInfo}`;
            timeLabel.style.color = 'green';
            infoContainer.appendChild(timeLabel);

            itemData.taskNameElement.parentElement.appendChild(infoContainer);
        }
    }


    function isVideoCompleted(coursewareElement) {
        let video = coursewareElement.querySelector('#dplayer video') || coursewareElement.querySelector('video');
        if (video) {
            const progress = (video.currentTime / video.duration) * 100;
            return progress >= 100;
        }
        return false;
    }

    function isPptCompleted(coursewareElement) {
        if (!coursewareElement) return false;
        if (coursewareElement.dataset.pptCompleted === 'true') return true;

        const completeIcon = coursewareElement.querySelector('img.file-complete');
        if (completeIcon) {
            const src = completeIcon.getAttribute('src');
            return src.includes(completionStatuses['已完成']);
        }
        return false;
    }


    function categorizeItems(items) {
        const categories = {};

        items.forEach(item => {
            if (processedItems.has(item)) return;

            const titleElement = item.querySelector('p.title, p.title-big');
            if (!titleElement) return;
            const titleText = titleElement.textContent.trim();

            let matchedCategory = '其他';
            for (const [category, keywords] of Object.entries(categoryKeywords)) {
                if (keywords.some(keyword => titleText.includes(keyword))) {
                    matchedCategory = category;
                    break;
                }
            }

            const itemData = {
                element: item.cloneNode(true),
                originalElement: item,
                title: titleText,
                replyStatus: '未回复'
            };

            if (matchedCategory === '课件') {
                let status = '未完成';
                const img = item.querySelector('img.file-complete');
                if (img) {
                    const src = img.getAttribute('src');
                    if (src === completionStatuses['已完成']) {
                        status = '已完成';
                    } else if (src === completionStatuses['半完成']) {
                        status = '半完成';
                    } else if (src === completionStatuses['未完成']) {
                        status = '未完成';
                    } else {
                        // 如果无法匹配到已知的图标,默认未完成
                        status = '未完成';
                    }
                }


                itemData.status = status;


                if (status === '未完成' || status === '半完成') {
                    coursewareQueues['默认未完成队列'].items.push(itemData);
                }
            }

            if (!categories[matchedCategory]) {
                categories[matchedCategory] = { items: [], completed: 0, halfCompleted: 0, total: 0 };
            }

            categories[matchedCategory].items.push(itemData);
            if (matchedCategory === '课件') {
                categories[matchedCategory].total += 1;
                if (itemData.status === '已完成') {
                    categories[matchedCategory].completed += 1;
                } else if (itemData.status === '半完成') {
                    categories[matchedCategory].halfCompleted += 1;
                }
            }

            processedItems.add(item);
        });

        return categories;
    }

    async function waitForContentLoaded(maxRetries = 40, intervalTime = 500) {
        return new Promise((resolve) => {
            let retries = 0;
            const interval = setInterval(() => {
                const items = document.querySelectorAll('.third-level-inner-box');
                if (items.length > 0 || retries >= maxRetries) {
                    clearInterval(interval);
                    resolve();
                }
                retries++;
            }, intervalTime);
        });
    }

    function createDisplayPanel() {
        if (document.getElementById('custom-display-container')) return document.getElementById('custom-display-container').querySelector('.panel-content');

        const displayContainer = document.createElement('div');
        displayContainer.id = 'custom-display-container';
        displayContainer.style.position = 'fixed';
        displayContainer.style.top = '10%';
        displayContainer.style.left = '10%';
        displayContainer.style.width = '500px';
        displayContainer.style.height = '600px';
        displayContainer.style.overflow = 'auto';
        displayContainer.style.backgroundColor = '#fff';
        displayContainer.style.border = '1px solid #ccc';
        displayContainer.style.borderRadius = '8px';
        displayContainer.style.boxShadow = '0 2px 8px rgba(0,0,0,0.2)';
        displayContainer.style.zIndex = '10000';
        displayContainer.style.display = 'block';

        const panelHeader = document.createElement('div');
        panelHeader.className = 'panel-header';
        panelHeader.style.backgroundColor = '#007bff';
        panelHeader.style.color = '#fff';
        panelHeader.style.padding = '10px';
        panelHeader.style.cursor = 'move';
        panelHeader.style.fontSize = '16px';
        panelHeader.style.fontWeight = 'bold';
        panelHeader.style.position = 'relative';
        panelHeader.textContent = '反馈群:1006332809  || Written by Abstract😉';

        const minimizeButton = document.createElement('button');
        minimizeButton.textContent = '—';
        minimizeButton.title = '最小化';
        minimizeButton.style.position = 'absolute';
        minimizeButton.style.top = '5px';
        minimizeButton.style.right = '10px';
        minimizeButton.style.background = 'transparent';
        minimizeButton.style.border = 'none';
        minimizeButton.style.color = '#fff';
        minimizeButton.style.fontSize = '18px';
        minimizeButton.style.cursor = 'pointer';

        minimizeButton.addEventListener('click', () => {
            displayContainer.style.display = 'none';
            restoreButton.style.display = 'block';
        });

        panelHeader.appendChild(minimizeButton);

        const panelContent = document.createElement('div');
        panelContent.className = 'panel-content';
        panelContent.style.padding = '10px';


        const instructionsDiv = document.createElement('div');
        instructionsDiv.style.marginBottom = '10px';
        instructionsDiv.style.padding = '10px';
        instructionsDiv.style.border = '1px solid #eee';
        instructionsDiv.style.borderRadius = '5px';
        instructionsDiv.style.backgroundColor = '#f9f9f9';
        instructionsDiv.innerHTML = `
            <strong><b>说明:***---  注意课件切换时间是固定的哦 ---***</b></strong><br>
            1. 页面需保持可见,不可最小化(意思是窗口可最小,但是页面不能缩没)<br>
            2. 使用定时切换和自定义任务队列对抗干扰因素&提高灵活性,比如说,最下面你可以设置课件切换间隔为1min创建队列,然后把所有ppt课件添加进去,也可以开3倍速设置个6分钟创建队列(具体看这个时长能不能覆盖完所有的视频,一般18分钟够了),把视频课件添加进去。<br>
            2. 视频倍速默认3x,可在面板中调整<br>
            3. 课件切换默认4分钟,可调整<br>
            4. 自动化回复取的是评论区第一条,一键回复速度比较快,存在漏回复情况,建议单个回复<br>
            5. 一键自动刷课从默认未完成队列开始(即4分钟切换的那个)<br>
            6. <b>推荐自定义队列使用,先创建队列(设置课件切换时间和名称),然后添加需要执行的课件(选中课件标题后面的白色框框),然后再划到最下面选中目标队列然后添加进去最后执行就行了</b>
        `;
        panelContent.appendChild(instructionsDiv);


        const speedSelectorContainer = document.createElement('div');
        speedSelectorContainer.style.marginTop = '15px';

        const speedLabel = document.createElement('label');
        speedLabel.textContent = '视频倍速: ';
        speedLabel.style.marginRight = '10px';
        speedLabel.style.fontWeight = 'bold';

        const speedSelector = document.createElement('select');
        speedSelector.style.padding = '5px';
        speedSelector.style.borderRadius = '3px';
        speedSelector.style.border = '1px solid #ccc';

        const speeds = [1, 2, 3];
        const storedSpeed = parseFloat(localStorage.getItem('videoPlaybackSpeed')) || 3;
        speeds.forEach(speed => {
            const option = document.createElement('option');
            option.value = speed;
            option.textContent = `${speed}x`;
            if (speed === storedSpeed) option.selected = true;
            speedSelector.appendChild(option);
        });

        speedSelector.addEventListener('change', () => {
            const selectedSpeed = parseFloat(speedSelector.value);
            localStorage.setItem('videoPlaybackSpeed', selectedSpeed);

           
            if (window.videoController && window.videoController.activeVideos) {
                window.videoController.activeVideos.forEach(task => {
                    if (task.video) {
                        task.video.playbackRate = selectedSpeed;
                    }
                });
            }
        });


        speedSelectorContainer.appendChild(speedLabel);
        speedSelectorContainer.appendChild(speedSelector);
        panelContent.appendChild(speedSelectorContainer);


        const intervalContainer = document.createElement('div');
        intervalContainer.style.marginTop = '15px';

        const intervalLabel = document.createElement('label');
        intervalLabel.textContent = '课件切换的间隔时间(秒): ';
        intervalLabel.style.marginRight = '10px';
        intervalLabel.style.fontWeight = 'bold';

        const intervalInput = document.createElement('input');
        intervalInput.type = 'number';
        intervalInput.style.width = '60px';
        intervalInput.value = (coursewareQueues['默认未完成队列'].interval / 1000).toString();
        intervalInput.style.padding = '5px';
        intervalInput.style.borderRadius = '3px';
        intervalInput.style.border = '1px solid #ccc';

        intervalInput.addEventListener('change', () => {
            let val = parseInt(intervalInput.value);
            if (isNaN(val) || val <= 0) {
                val = 240;
            }
            coursewareQueues['默认未完成队列'].interval = val * 1000;
            localStorage.setItem('autoInterval', coursewareQueues['默认未完成队列'].interval);
        });

        intervalContainer.appendChild(intervalLabel);
        intervalContainer.appendChild(intervalInput);
        panelContent.appendChild(intervalContainer);


        const restoreButton = document.createElement('button');
        restoreButton.id = 'restore-button';
        restoreButton.textContent = 'Be yourself and Dream bigger😉';
        restoreButton.style.position = 'fixed';
        restoreButton.style.bottom = '20px';
        restoreButton.style.left = '20px';
        restoreButton.style.zIndex = '10001';
        restoreButton.style.padding = '10px 20px';
        restoreButton.style.backgroundColor = '#007bff';
        restoreButton.style.color = '#fff';
        restoreButton.style.border = 'none';
        restoreButton.style.borderRadius = '5px';
        restoreButton.style.cursor = 'pointer';
        restoreButton.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
        restoreButton.style.display = 'none';

        restoreButton.addEventListener('click', () => {
            displayContainer.style.display = 'block';
            restoreButton.style.display = 'none';
        });

        document.body.appendChild(restoreButton);

        displayContainer.appendChild(panelHeader);
        displayContainer.appendChild(panelContent);
        document.body.appendChild(displayContainer);

        makeElementDraggable(displayContainer);

        return panelContent;
    }

    function makeElementDraggable(elmnt) {
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        const header = elmnt.querySelector(".panel-header");
        if (header) {
            header.style.cursor = 'move';
            header.onmousedown = dragMouseDown;
        }

        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDragElement;
            document.onmousemove = elementDrag;
        }

        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();
            pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            let newTop = elmnt.offsetTop - pos2;
            let newLeft = elmnt.offsetLeft - pos1;

            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;
            const elemWidth = elmnt.offsetWidth;
            const elemHeight = elmnt.offsetHeight;

            if (newTop < 0) newTop = 0;
            if (newLeft < 0) newLeft = 0;
            if (newTop + elemHeight > windowHeight) newTop = windowHeight - elemHeight;
            if (newLeft + elemWidth > windowWidth) newLeft = windowWidth - elemWidth;

            elmnt.style.top = newTop + "px";
            elmnt.style.left = newLeft + "px";
        }

        function closeDragElement() {
            document.onmouseup = null;
            document.onmousemove = null;
        }
    }

    function populatePanel(panelContent, categories) {

        const autoButton = document.createElement('button');
        autoButton.textContent = '一键自动刷课(默认未完成队列)';
        autoButton.style.width = '100%';
        autoButton.style.padding = '10px';
        autoButton.style.marginBottom = '15px';
        autoButton.style.backgroundColor = '#28a745';
        autoButton.style.color = '#fff';
        autoButton.style.border = 'none';
        autoButton.style.borderRadius = '5px';
        autoButton.style.cursor = 'pointer';
        autoButton.style.fontSize = '16px';
        autoButton.style.zIndex = '10001';

        autoButton.addEventListener('click', async () => {
            if (isQueueProcessing) {
                alert('已有队列在执行,请稍后。');
                return;
            }
            currentQueueName = '默认未完成队列';
            await startQueueProcessing(currentQueueName);
        });

        panelContent.appendChild(autoButton);


        if (categories['讨论'] && categories['讨论'].items.length > 0) {
            const data = categories['讨论'];
            const progressLabel = document.createElement('span');
            progressLabel.textContent = `已回复:0/${data.items.length}`;
            progressLabel.style.fontSize = '14px';

            const replyAllButton = document.createElement('button');
            replyAllButton.textContent = '讨论区一键自动回复';
            replyAllButton.style.width = '100%';
            replyAllButton.style.padding = '10px';
            replyAllButton.style.marginBottom = '5px';
            replyAllButton.style.backgroundColor = '#4caf50';
            replyAllButton.style.color = '#fff';
            replyAllButton.style.border = 'none';
            replyAllButton.style.borderRadius = '5px';
            replyAllButton.style.cursor = 'pointer';
            replyAllButton.style.fontSize = '14px';

            replyAllButton.addEventListener('click', async () => {
                await performBatchAutoReply(data, progressLabel);
            });

            panelContent.appendChild(replyAllButton);
            panelContent.appendChild(progressLabel);
        }


        if (categories['测验'] && categories['测验'].items.length > 0) {
            const data = categories['测验'];
            const testProgress = document.createElement('span');
            testProgress.textContent = `已获取:0/${data.items.length}`;
            testProgress.style.fontSize = '14px';

            const getInfoButton = document.createElement('button');
            getInfoButton.textContent = '获取测验作答信息';
            getInfoButton.style.width = '100%';
            getInfoButton.style.padding = '10px';
            getInfoButton.style.marginBottom = '5px';
            getInfoButton.style.backgroundColor = '#17a2b8';
            getInfoButton.style.color = '#fff';
            getInfoButton.style.border = 'none';
            getInfoButton.style.borderRadius = '5px';
            getInfoButton.style.cursor = 'pointer';
            getInfoButton.style.fontSize = '14px';

            getInfoButton.addEventListener('click', () => {
                collectTestAttempts(data, testProgress);
            });

            panelContent.appendChild(getInfoButton);
            panelContent.appendChild(testProgress);
        }


        if (categories['作业'] && categories['作业'].items.length > 0) {
            const data = categories['作业'];
            const assignmentProgress = document.createElement('span');
            assignmentProgress.textContent = `已获取:0/${data.items.length}`;
            assignmentProgress.style.fontSize = '14px';

            const getAssignmentButton = document.createElement('button');
            getAssignmentButton.textContent = '获取作业信息';
            getAssignmentButton.style.width = '100%';
            getAssignmentButton.style.padding = '10px';
            getAssignmentButton.style.marginBottom = '5px';
            getAssignmentButton.style.backgroundColor = '#ffc107';
            getAssignmentButton.style.color = '#fff';
            getAssignmentButton.style.border = 'none';
            getAssignmentButton.style.borderRadius = '5px';
            getAssignmentButton.style.cursor = 'pointer';
            getAssignmentButton.style.fontSize = '14px';

            getAssignmentButton.addEventListener('click', () => {
                collectAssignmentInfo(data, assignmentProgress);
            });

            panelContent.appendChild(getAssignmentButton);
            panelContent.appendChild(assignmentProgress);
        }


        for (const [categoryName, data] of Object.entries(categories)) {
            const categoryPanel = document.createElement('div');
            categoryPanel.className = 'category-panel';
            categoryPanel.style.border = '1px solid #ccc';
            categoryPanel.style.margin = '10px 0';
            categoryPanel.style.borderRadius = '5px';
            categoryPanel.style.overflow = 'hidden';

            const headerContainer = document.createElement('div');
            headerContainer.style.display = 'flex';
            headerContainer.style.justifyContent = 'space-between';
            headerContainer.style.alignItems = 'center';
            headerContainer.style.background = '#f0f0f0';
            headerContainer.style.padding = '10px';
            headerContainer.style.cursor = 'pointer';
            headerContainer.style.fontWeight = 'bold';
            headerContainer.style.fontSize = '14px';

            const header = document.createElement('div');
            if (categoryName === '课件') {
                const progress = `${data.completed}/${data.total}`;
                const halfProgress = data.halfCompleted;
                header.textContent = `课件 (已完成: ${progress}, 半完成: ${halfProgress})`;
            } else {
                header.textContent = `${categoryName} (${data.items.length})`;
            }
            headerContainer.appendChild(header);

            const content = document.createElement('div');
            content.className = 'category-content';
            content.style.display = 'none';
            content.style.padding = '10px';

            data.items.forEach(itemData => {
                const taskItem = document.createElement('div');
                taskItem.className = 'task-item';
                taskItem.style.marginBottom = '5px';
                taskItem.style.display = 'flex';
                taskItem.style.alignItems = 'center';
                taskItem.style.justifyContent = 'space-between';

                const leftContent = document.createElement('div');
                leftContent.style.display = 'flex';
                leftContent.style.alignItems = 'center';
                leftContent.style.flex = '1';


                if (categoryName === '课件') {
                    const statusIcon = document.createElement('img');
                    statusIcon.style.width = '16px';
                    statusIcon.style.height = '16px';
                    statusIcon.style.marginRight = '10px';
                    statusIcon.src = completionStatuses[itemData.status || '未完成'];
                    leftContent.appendChild(statusIcon);
                }

                const taskName = document.createElement('span');
                taskName.textContent = itemData.title;
                leftContent.appendChild(taskName);

                itemData.taskNameElement = taskName;


                if (categoryName === '讨论') {
                    const statusLabel = document.createElement('span');
                    statusLabel.textContent = '未回复';
                    statusLabel.style.marginLeft = '10px';
                    statusLabel.style.color = 'red';
                    statusLabel.className = 'reply-status';
                    itemData.replyStatusElement = statusLabel;
                    leftContent.appendChild(statusLabel);
                }

                const buttonsContainer = document.createElement('div');
                buttonsContainer.style.display = 'flex';
                buttonsContainer.style.gap = '5px';


                const itemJumpButton = document.createElement('button');
                itemJumpButton.textContent = '跳转';
                itemJumpButton.style.padding = '2px 8px';
                itemJumpButton.style.fontSize = '12px';
                itemJumpButton.style.cursor = 'pointer';
                itemJumpButton.style.backgroundColor = '#007bff';
                itemJumpButton.style.color = '#fff';
                itemJumpButton.style.border = 'none';
                itemJumpButton.style.borderRadius = '3px';

                itemJumpButton.addEventListener('click', async (e) => {
                    e.stopPropagation();
                    await jumpToContentItem(itemData.originalElement);
                });
                buttonsContainer.appendChild(itemJumpButton);


                if (categoryName === '讨论') {
                    const itemReplyButton = document.createElement('button');
                    itemReplyButton.textContent = '自动回复';
                    itemReplyButton.style.padding = '2px 8px';
                    itemReplyButton.style.fontSize = '12px';
                    itemReplyButton.style.cursor = 'pointer';
                    itemReplyButton.style.backgroundColor = '#4caf50';
                    itemReplyButton.style.color = '#fff';
                    itemReplyButton.style.border = 'none';
                    itemReplyButton.style.borderRadius = '3px';

                    itemReplyButton.addEventListener('click', async (e) => {
                        e.stopPropagation();
                        await performAutoReply(itemData);
                    });
                    buttonsContainer.appendChild(itemReplyButton);
                }


                if (categoryName === '课件') {
                    const queueCheckbox = document.createElement('input');
                    queueCheckbox.type = 'checkbox';
                    queueCheckbox.title = '选择本课件加入自定义队列';
                    itemData.queueCheckbox = queueCheckbox;
                    buttonsContainer.appendChild(queueCheckbox);
                }

                taskItem.appendChild(leftContent);
                taskItem.appendChild(buttonsContainer);
                content.appendChild(taskItem);
            });

            headerContainer.addEventListener('click', () => {
                content.style.display = content.style.display === 'none' ? 'block' : 'none';
            });

            categoryPanel.appendChild(headerContainer);
            categoryPanel.appendChild(content);

            panelContent.appendChild(categoryPanel);
        }
    }

    function createQueueUI(panelContent, categories) {
        const queueContainer = document.createElement('div');
        queueContainer.style.marginTop = '20px';
        queueContainer.style.borderTop = '1px solid #ddd';
        queueContainer.style.paddingTop = '10px';

        const queueTitle = document.createElement('div');
        queueTitle.textContent = '自定义队列管理(仅课件)';
        queueTitle.style.fontWeight = 'bold';
        queueTitle.style.marginBottom = '10px';
        queueContainer.appendChild(queueTitle);

        const queueList = document.createElement('div');
        queueList.id = 'queue-list';
        queueContainer.appendChild(queueList);

        function renderQueueList() {
            queueList.innerHTML = '';
            for (const [qName, qData] of Object.entries(coursewareQueues)) {
                const qDiv = document.createElement('div');
                qDiv.style.marginBottom = '5px';
                qDiv.style.display = 'flex';
                qDiv.style.alignItems = 'center';
                qDiv.style.justifyContent = 'space-between';

                const qInfo = document.createElement('span');
                qInfo.textContent = `${qName} (任务数: ${qData.items.length}, 间隔: ${qData.interval/1000}s)`;
                qDiv.appendChild(qInfo);

                const runBtn = document.createElement('button');
                runBtn.textContent = '运行队列';
                runBtn.style.fontSize = '12px';
                runBtn.style.padding = '2px 5px';
                runBtn.style.cursor = 'pointer';
                runBtn.style.backgroundColor = '#28a745';
                runBtn.style.color = '#fff';
                runBtn.style.border = 'none';
                runBtn.style.borderRadius = '3px';
                runBtn.addEventListener('click', async () => {
                    if (isQueueProcessing) {
                        alert('已有队列在执行,请稍后。');
                        return;
                    }
                    currentQueueName = qName;
                    await startQueueProcessing(qName);
                });
                qDiv.appendChild(runBtn);

                if (qName !== '默认未完成队列') {
                    const deleteBtn = document.createElement('button');
                    deleteBtn.textContent = '删除队列';
                    deleteBtn.style.fontSize = '12px';
                    deleteBtn.style.padding = '2px 5px';
                    deleteBtn.style.cursor = 'pointer';
                    deleteBtn.style.backgroundColor = '#dc3545';
                    deleteBtn.style.color = '#fff';
                    deleteBtn.style.border = 'none';
                    deleteBtn.style.borderRadius = '3px';
                    deleteBtn.addEventListener('click', () => {
                        delete coursewareQueues[qName];
                        renderQueueList();
                    });
                    qDiv.appendChild(deleteBtn);
                }

                queueList.appendChild(qDiv);
            }
        }

        renderQueueList();

        const createQueueForm = document.createElement('div');
        createQueueForm.style.marginTop = '10px';

        const queueNameInput = document.createElement('input');
        queueNameInput.type = 'text';
        queueNameInput.placeholder = '输入新队列名称';
        queueNameInput.style.marginRight = '10px';
        queueNameInput.style.padding = '5px';

        const queueIntervalInput = document.createElement('input');
        queueIntervalInput.type = 'number';
        queueIntervalInput.placeholder = '间隔(秒)';
        queueIntervalInput.value = 240;
        queueIntervalInput.style.marginRight = '10px';
        queueIntervalInput.style.padding = '5px';
        queueIntervalInput.style.width = '60px';

        const createBtn = document.createElement('button');
        createBtn.textContent = '创建队列';
        createBtn.style.padding = '5px 10px';
        createBtn.style.backgroundColor = '#007bff';
        createBtn.style.color = '#fff';
        createBtn.style.border = 'none';
        createBtn.style.borderRadius = '3px';
        createBtn.style.cursor = 'pointer';

        createBtn.addEventListener('click', () => {
            const qName = queueNameInput.value.trim();
            const qInterval = parseInt(queueIntervalInput.value) * 1000;

            if (!qName) {
                alert('请填写队列名称');
                return;
            }

            if (isNaN(qInterval) || qInterval <= 0) {
                alert('间隔时间无效');
                return;
            }

            if (coursewareQueues[qName]) {
                alert('该队列名称已存在,请换一个。');
                return;
            }

            coursewareQueues[qName] = {
                items: [],
                interval: qInterval
            };

            queueNameInput.value = '';
            queueIntervalInput.value = '240';
            renderQueueList();
            refreshQueueSelect();
        });

        createQueueForm.appendChild(queueNameInput);
        createQueueForm.appendChild(queueIntervalInput);
        createQueueForm.appendChild(createBtn);

        const addToQueueContainer = document.createElement('div');
        addToQueueContainer.style.marginTop = '10px';

        const queueSelect = document.createElement('select');
        function refreshQueueSelect() {
            const selected = queueSelect.value;
            queueSelect.innerHTML = '';
            Object.keys(coursewareQueues).forEach(qName => {
                const opt = document.createElement('option');
                opt.value = qName;
                opt.textContent = qName;
                queueSelect.appendChild(opt);
            });
            if (coursewareQueues[selected]) {
                queueSelect.value = selected;
            }
        }

        refreshQueueSelect();
        queueSelect.style.marginRight = '10px';
        queueSelect.style.padding = '5px';

        const addSelectedBtn = document.createElement('button');
        addSelectedBtn.textContent = '添加选中课件到队列';
        addSelectedBtn.style.padding = '5px 10px';
        addSelectedBtn.style.backgroundColor = '#28a745';
        addSelectedBtn.style.color = '#fff';
        addSelectedBtn.style.border = 'none';
        addSelectedBtn.style.borderRadius = '3px';
        addSelectedBtn.style.cursor = 'pointer';

        addSelectedBtn.addEventListener('click', () => {
            const selectedQueue = queueSelect.value;
            const allCheckboxes = document.querySelectorAll('.category-panel .task-item input[type="checkbox"]');
            allCheckboxes.forEach(chk => {
                if (chk.checked) {
                    const listItem = chk.closest('.task-item');
                    const titleSpan = listItem.querySelector('span');
                    const titleText = titleSpan ? titleSpan.textContent.trim() : '';
                    for (const cat of Object.values(categories)) {
                        if (!cat.items) continue;
                        const it = cat.items.find(d => d.title === titleText);
                        if (it) {
                            // 确保是课件才加入队列
                            const catName = Object.entries(categories).find(([k,v])=>v.items.includes(it))?.[0]||'';
                            if (catName === '课件' && !coursewareQueues[selectedQueue].items.includes(it)) {
                                coursewareQueues[selectedQueue].items.push(it);
                            }
                        }
                    }
                    chk.checked = false;
                }
            });
            refreshQueueSelect();
            alert('已添加到队列');
            renderQueueList();
        });

        addToQueueContainer.appendChild(queueSelect);
        addToQueueContainer.appendChild(addSelectedBtn);

        queueContainer.appendChild(createQueueForm);
        queueContainer.appendChild(addToQueueContainer);

        panelContent.appendChild(queueContainer);
    }


    async function startQueueProcessing(queueName) {
        if (!coursewareQueues[queueName]) {
            alert('队列不存在');
            return;
        }

        if (coursewareQueues[queueName].items.length === 0) {
            alert('队列中无课件');
            return;
        }

        isQueueProcessing = true;
        const qData = coursewareQueues[queueName];

        for (const itemData of qData.items) {
            if (document.hidden) break;
            await jumpToContentItem(itemData.originalElement);
            await new Promise(res => setTimeout(res, 1000));

            if (hasPPT(itemData.originalElement)) {
                const pptIframe = itemData.originalElement.querySelector('iframe');
                if (pptIframe) {
                    const pptTaskId = `ppt-${Date.now()}-${Math.random().toString(36).substr(2,5)}`;
                    const iframeSrc = new URL(pptIframe.src);
                    iframeSrc.searchParams.set('pptTaskId', pptTaskId);
                    pptIframe.src = iframeSrc.toString();

                    const pptPromise = window.videoController.createPPTTask(pptTaskId);
                    await pptPromise;
                }
            } else if (hasVideo(itemData.originalElement)) {
                const videoEl = itemData.originalElement.querySelector('#dplayer video') || itemData.originalElement.querySelector('video');
                if (videoEl) {
                    const videoTaskId = `video-${Date.now()}-${Math.random().toString(36).substr(2,5)}`;
                    const videoPromise = window.videoController.handleVideo(videoEl, videoTaskId);
                    await videoPromise;
                }
            }

            await new Promise(res => setTimeout(res, qData.interval));
        }

        isQueueProcessing = false;
        currentQueueName = null;
        alert(`${queueName} 执行完成!`);
    }

    function hasPPT(element) {
        return !!element.querySelector('.slide-img-container');
    }

    function hasVideo(element) {
        return !!element.querySelector('#dplayer') || !!element.querySelector('video');
    }

    function initPptAutoPaging() {
        const progressBarSelector = '.bottom-paging-progress .bar';
        const nextPageButtonSelector = '.slide-img-container.context-menu-disabled .ppt-turn-right-mask';
        const checkInterval = 1000;
        let hasReportedCompletion = false;

        let pptIntervalId = setInterval(() => {
            const pptBar = document.querySelector(progressBarSelector);
            const nextButton = document.querySelector(nextPageButtonSelector);

            if (pptBar) {
                let width = parseFloat(pptBar.style.width) || 0;
                if (width >= 100 && !hasReportedCompletion) {
                    hasReportedCompletion = true;
                    clearInterval(pptIntervalId);
                    window.parent.postMessage({
                        type: 'pptCompleted',
                        status: 'completed',
                        timestamp: Date.now()
                    }, '*');
                    return;
                }
                if (width < 100 && nextButton) {
                    simulateClick(nextButton);
                }
            }
        }, checkInterval);

        pptTimeoutId = setTimeout(() => {
            if (!hasReportedCompletion) {
                hasReportedCompletion = true;
                clearInterval(pptIntervalId);
                window.parent.postMessage({
                    type: 'pptCompleted',
                    status: 'completed',
                    timestamp: Date.now()
                }, '*');
            }
        }, 60000);
    }

    async function initialize() {
        await waitForContentLoaded();
        const items = document.querySelectorAll('.third-level-inner-box');
        const categorized = categorizeItems(items);
        const panelContent = createDisplayPanel();
        populatePanel(panelContent, categorized);
        createQueueUI(panelContent, categorized);
    }


    class VideoController {
        constructor() {
            this.activeVideos = new Map();
            this.pptPromises = new Map();
            this.container = this.createAutoPlayerInterface();
            this.taskContainer = this.container.querySelector('#autoplay-task-container');
            this.activePPTs = new Map();

            document.addEventListener('visibilitychange', () => this.handleVisibilityChange());
            window.addEventListener('message', (event) => this.handleMessage(event), false);
        }

        createAutoPlayerInterface() {
            if (document.getElementById('autoplay-control-panel')) return document.getElementById('autoplay-control-panel');

            const container = document.createElement('div');
            container.id = 'autoplay-control-panel';
            container.style.cssText = `
                position: fixed;
                bottom: 20px;
                right: 20px;
                width: 300px;
                height: 400px;
                background: rgba(0, 0, 0, 0.8);
                color: white;
                padding: 15px;
                border-radius: 8px;
                font-family: Arial, sans-serif;
                z-index: 9999;
                box-shadow: 0 2px 10px rgba(0,0,0,0.3);
                overflow-y: auto;
            `;

            container.innerHTML = `
                <div style="font-weight:bold;font-size:16px;margin-bottom:10px;">视频/PPT自动播放面板</div>
                <div id="autoplay-task-container"></div>
            `;

            document.body.appendChild(container);
            return container;
        }

        handleMessage(event) {
            if (event.origin !== `https://${IFRAME_PAGE_HOST}`) return;
            const data = event.data;
            if (!data.type) return;

            if (data.type === 'pptCompleted') {
                this.updateTaskUI(data.taskId, 100, 'completed');
                this.activePPTs.delete(data.taskId);
                if (this.pptPromises.has(data.taskId)) {
                    this.pptPromises.get(data.taskId).resolve();
                    this.pptPromises.delete(data.taskId);
                }
            } else if (data.type === 'pptProgress') {
                this.updateTaskUI(data.taskId, data.progress, 'playing');
                if (this.activePPTs.has(data.taskId)) {
                    const pptTask = this.activePPTs.get(data.taskId);
                    pptTask.progress = data.progress;
                }
            }
        }

        createTaskElement(taskId, title = `任务 #${taskId}`) {
            const taskDiv = document.createElement('div');
            taskDiv.id = `task-${taskId}`;
            taskDiv.className = 'task-item';
            taskDiv.style.cssText = `
                margin-bottom: 10px;
                padding: 8px;
                background: rgba(255, 255, 255, 0.1);
                border-radius: 4px;
            `;

            taskDiv.innerHTML = `
                <div style="font-weight:bold;">${title}</div>
                <div class="task-status">状态: 初始化中</div>
                <div style="margin-top:5px;position:relative;height:5px;background:#444;">
                    <div class="progress-fill" style="height:5px;width:0%;background:#28a745;"></div>
                </div>
            `;

            this.taskContainer.appendChild(taskDiv);
            return taskDiv;
        }

        updateTaskUI(taskId, progress, status) {
            const taskElement = document.querySelector(`#task-${taskId}`);
            if (taskElement) {
                const progressFill = taskElement.querySelector('.progress-fill');
                const statusText = taskElement.querySelector('.task-status');

                if (progressFill) {
                    progressFill.style.width = `${progress}%`;
                }
                if (statusText) {
                    statusText.textContent = `状态: ${status} (${progress.toFixed(1)}%)`;
                }
            }
        }

        createPPTTask(taskId) {
            this.createTaskElement(taskId, `PPT任务 #${taskId}`);
            this.activePPTs.set(taskId, {
                id: taskId,
                progress: 0,
                status: 'playing'
            });

            let resolveFunc;
            const promise = new Promise((resolve) => {
                resolveFunc = resolve;
            });
            this.pptPromises.set(taskId, { resolve: resolveFunc });
            return promise;
        }

        handleVideo(video, taskId) {
            return new Promise(async (resolve, reject) => {
                if (!video) {
                    reject(new Error('未找到视频元素'));
                    return;
                }

                this.createTaskElement(taskId, `视频任务 #${taskId}`);

                try {
                    video.muted = true;
                    video.autoplay = true;
                    video.playsInline = true;
                    video.setAttribute('webkit-playsinline', 'true');

                    const applyPlaybackRate = () => {
                        const playbackRate = parseFloat(localStorage.getItem('videoPlaybackSpeed')) || 3;
                        video.playbackRate = playbackRate;
                    };

                  
                    const onLoadedMetadata = () => {
                        applyPlaybackRate();
                    };
                    video.addEventListener('loadedmetadata', onLoadedMetadata, { once: true });

                   
                    const onCanPlay = () => {
                        applyPlaybackRate();
                    };
                    video.addEventListener('canplay', onCanPlay, { once: true });

                    const onTimeUpdate = () => {
                        if (!video.duration) return;
                        const progress = (video.currentTime / video.duration) * 100;
                        this.updateTaskUI(taskId, progress, 'playing');

                        if (progress >= 99.9) {
                            this.updateTaskUI(taskId, 100, 'completed');
                            video.removeEventListener('timeupdate', onTimeUpdate);
                        
                            video.removeEventListener('loadedmetadata', onLoadedMetadata);
                            video.removeEventListener('canplay', onCanPlay);
                            resolve();
                        }
                    };

                    video.addEventListener('timeupdate', onTimeUpdate);

                    await video.play();
                  
                    applyPlaybackRate();

                    this.updateTaskUI(taskId, 0, 'playing');
                } catch (error) {
                    console.error('视频播放错误:', error);
                    this.updateTaskUI(taskId, 0, 'error');
                    reject(error);
                }
            });
        }


        handleVisibilityChange() {}
    }

    if (window.location.hostname === MAIN_PAGE_HOST) {
        window.videoController = new VideoController();
      
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                mutation.addedNodes.forEach((node) => {
                    if (node.nodeType === 1) {
                        const videoPlayer = node.id === 'dplayer' ? node : node.querySelector('#dplayer');
                        if (videoPlayer && !videoPlayer.dataset.autoplayInitialized) {
                            videoPlayer.dataset.autoplayInitialized = 'true';
                            const videoTaskId = `video-${Date.now()}-${Math.random().toString(36).substr(2,5)}`;
                            window.videoController.handleVideo(videoPlayer.querySelector('video'), videoTaskId);
                        }

                        const pptIframe = (node.tagName === 'IFRAME') ? node : node.querySelector('iframe');
                        if (pptIframe && !pptIframe.dataset.pptInitialized && pptIframe.src.includes('preview.cqooc.com')) {
                            pptIframe.dataset.pptInitialized = 'true';
                            const pptTaskId = `ppt-${Date.now()}-${Math.random().toString(36).substr(2,5)}`;
                            const iframeSrc = new URL(pptIframe.src);
                            iframeSrc.searchParams.set('pptTaskId', pptTaskId);
                            pptIframe.src = iframeSrc.toString();
                            window.videoController.createPPTTask(pptTaskId);
                        }
                    }
                });
            });
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        initialize();

    } else if (window.location.hostname === IFRAME_PAGE_HOST) {
        initPptAutoPaging();
    }

})();


(function() {
    'use strict';

    const API_URL = 'https://api.siliconflow.cn/v1/chat/completions';
    const API_KEY = 'sk-bxignvnkxpnoswzugchqmygyfwebfggbntiicrqjsipgvpoe';
    const MODEL = 'Qwen/Qwen2.5-7B-Instruct';
    const MAX_TOKENS = 1024;
    const MAX_SUBMIT_RETRIES = 5;


    const controlPanel = document.createElement('div');
    controlPanel.id = 'customControlPanel';
    controlPanel.style.position = 'fixed';
    controlPanel.style.top = '20px';
    controlPanel.style.right = '20px';
    controlPanel.style.width = '400px';
    controlPanel.style.background = '#ffffff';
    controlPanel.style.border = '1px solid #ccc';
    controlPanel.style.borderRadius = '10px';
    controlPanel.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.1)';
    controlPanel.style.zIndex = '10000';
    controlPanel.style.fontFamily = 'Arial, sans-serif';
    controlPanel.style.fontSize = '14px';
    controlPanel.style.transition = 'all 0.3s ease';
    controlPanel.style.color = '#333';
    controlPanel.style.display = 'flex';
    controlPanel.style.flexDirection = 'column';


    let isDragging = false;
    let offsetX, offsetY;
    let animationFrame;

    controlPanel.addEventListener('mousedown', function(e) {
        if (e.target.classList.contains('panel-header')) {
            isDragging = true;
            offsetX = e.clientX - controlPanel.offsetLeft;
            offsetY = e.clientY - controlPanel.offsetTop;
            e.preventDefault();
        }
    });

    document.addEventListener('mousemove', function(e) {
        if (isDragging) {
            if (animationFrame) cancelAnimationFrame(animationFrame);
            animationFrame = requestAnimationFrame(() => {
                controlPanel.style.left = (e.clientX - offsetX) + 'px';
                controlPanel.style.top = (e.clientY - offsetY) + 'px';
                controlPanel.style.right = 'auto';
            });
        }
    });

    document.addEventListener('mouseup', function() {
        isDragging = false;
    });


    const panelHeader = document.createElement('div');
    panelHeader.className = 'panel-header';
    panelHeader.style.backgroundColor = '#6200EE';
    panelHeader.style.padding = '12px 16px';
    panelHeader.style.cursor = 'move';
    panelHeader.style.borderTopLeftRadius = '10px';
    panelHeader.style.borderTopRightRadius = '10px';
    panelHeader.style.display = 'flex';
    panelHeader.style.justifyContent = 'space-between';
    panelHeader.style.alignItems = 'center';
    panelHeader.style.userSelect = 'none';

    const panelTitle = document.createElement('div');
    panelTitle.innerText = ' - 作业区 - ';
    panelTitle.style.color = '#FFFFFF';
    panelTitle.style.fontWeight = 'bold';
    panelHeader.appendChild(panelTitle);


    const minimizeButton = document.createElement('button');
    minimizeButton.innerHTML = '&#x2212;';
    minimizeButton.title = '最小化';
    minimizeButton.style.background = 'transparent';
    minimizeButton.style.border = 'none';
    minimizeButton.style.color = '#FFFFFF';
    minimizeButton.style.cursor = 'pointer';
    minimizeButton.style.fontSize = '20px';
    minimizeButton.style.lineHeight = '20px';
    minimizeButton.style.padding = '0';
    minimizeButton.style.margin = '0';
    minimizeButton.style.width = '24px';
    minimizeButton.style.height = '24px';
    minimizeButton.style.display = 'flex';
    minimizeButton.style.alignItems = 'center';
    minimizeButton.style.justifyContent = 'center';
    minimizeButton.style.transition = 'transform 0.2s';

    minimizeButton.addEventListener('mouseenter', () => {
        minimizeButton.style.transform = 'scale(1.2)';
    });
    minimizeButton.addEventListener('mouseleave', () => {
        minimizeButton.style.transform = 'scale(1)';
    });

    minimizeButton.addEventListener('click', () => {
        if (contentContainer.style.display === 'none') {
            contentContainer.style.display = 'block';
            minimizeButton.innerHTML = '&#x2212;';
            controlPanel.style.width = '400px';
        } else {
            contentContainer.style.display = 'none';
            minimizeButton.innerHTML = '&#x25B6;';
            controlPanel.style.width = '45px';
        }
    });

    panelHeader.appendChild(minimizeButton);
    controlPanel.appendChild(panelHeader);


    const contentContainer = document.createElement('div');
    contentContainer.style.padding = '16px';
    contentContainer.style.display = 'block';
    contentContainer.style.flex = '1';
    controlPanel.appendChild(contentContainer);


    const instructions = document.createElement('div');
    instructions.id = 'instructions';
    instructions.style.marginBottom = '20px';
    instructions.style.maxHeight = '200px';
    instructions.style.overflowY = 'auto';
    instructions.style.padding = '12px';
    instructions.style.backgroundColor = '#f9f9f9';
    instructions.style.borderRadius = '8px';
    instructions.style.border = '1px solid #ddd';
instructions.innerHTML = '<strong>说明:</strong><br>' +
    '1. 把两个开始自动完成的按钮点开,然后进入您想完成的作业或测试页面,系统将会自动完成。<br>' +
    '2. 目前支持单选、多选、判断和论述题。<br>' +
    '3. 如果题目或答案中包含图片,本次答案不准确,仅能处理纯文本问题。<br>'+'4. 用的是免费模型,如果你对精确度有更高要求,可以来找我<br>'+'5. 含论述题时,可能需要手动点击论述题的框它才会认为是输入完成才会自动提交<br>' +
    '6. 多选题可能会漏选,这时候刷新一下也许会解决<br>' + '7. 自动提交可能会在第二次才生效<br>' + '8. 虽然我是作者,但是有些问题我也不知道,刷新能解决80%的问题<br>' +'9. 毕竟是大模型回答,科学性和常识性的OK,其余像什么酒吧的场景就不行了。<br>' + '10. 我是反对刷题的哈,仅供学习用途-_-。';

    contentContainer.appendChild(instructions);


    const autoAnswerSection = document.createElement('div');
    autoAnswerSection.style.marginBottom = '20px';

    const autoAnswerTitle = document.createElement('div');
    autoAnswerTitle.innerText = '自动完成测验和考试';
    autoAnswerTitle.style.fontWeight = 'bold';
    autoAnswerTitle.style.marginBottom = '10px';
    autoAnswerTitle.style.color = '#6200EE';
    autoAnswerSection.appendChild(autoAnswerTitle);


    function createButton(text, bgColor, hoverColor, textColor) {
        const button = document.createElement('button');
        button.innerText = text;
        button.style.margin = '8px 0';
        button.style.padding = '10px 16px';
        button.style.width = '100%';
        button.style.backgroundColor = bgColor;
        button.style.border = 'none';
        button.style.borderRadius = '8px';
        button.style.cursor = 'pointer';
        button.style.color = textColor;
        button.style.fontSize = '14px';
        button.style.transition = 'background-color 0.3s, transform 0.2s';
        button.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.1)';
        button.style.display = 'flex';
        button.style.alignItems = 'center';
        button.style.justifyContent = 'center';
        button.style.fontWeight = '500';
        button.addEventListener('mouseover', () => {
            button.style.backgroundColor = hoverColor;
            button.style.transform = 'translateY(-2px)';
        });
        button.addEventListener('mouseout', () => {
            button.style.backgroundColor = bgColor;
            button.style.transform = 'translateY(0)';
        });
        return button;
    }


    const startAnswerButton = createButton('开始自动完成', '#6200EE', '#3700B3', '#FFFFFF');
    autoAnswerSection.appendChild(startAnswerButton);


    const toggleAutoSubmitButton = createButton('开启自动提交', '#03DAC6', '#018786', '#000000');
    autoAnswerSection.appendChild(toggleAutoSubmitButton);

    contentContainer.appendChild(autoAnswerSection);


    const autoCompleteSection = document.createElement('div');

    const autoCompleteTitle = document.createElement('div');
    autoCompleteTitle.innerText = '自动完成作业';
    autoCompleteTitle.style.fontWeight = 'bold';
    autoCompleteTitle.style.marginBottom = '10px';
    autoCompleteTitle.style.color = '#6200EE';
    autoCompleteSection.appendChild(autoCompleteTitle);


    const startCompleteButton = createButton('开始自动完成', '#03A9F4', '#0288D1', '#FFFFFF');
    autoCompleteSection.appendChild(startCompleteButton);


    const toggleAutoSaveButton = createButton('开启自动保存', '#FF9800', '#F57C00', '#FFFFFF');
    autoCompleteSection.appendChild(toggleAutoSaveButton);

    contentContainer.appendChild(autoCompleteSection);

    document.body.appendChild(controlPanel);


    let autoSubmitting = false;
    let answering = false;
    let answerObserver = null;
    let submitRetryCount = 0;


    let autoSave = false;
    let completing = false;
    let completeObserver = null;


    function log(message, type = 'info') {
        const timestamp = new Date().toLocaleTimeString();
        console.log(`[${timestamp}][自动任务脚本] ${message}`);
    }



    startAnswerButton.addEventListener('click', () => {
        if (!answering) {
            answering = true;
            startAnswerButton.innerText = '停止自动完成';
            startAnswerButton.style.backgroundColor = '#3700B3';
            log('开始自动完成测验和考试');
            observeQuestions();
        } else {
            answering = false;
            startAnswerButton.innerText = '开始自动完成';
            startAnswerButton.style.backgroundColor = '#6200EE';
            log('停止自动完成测验和考试');
            disconnectAnswerObserver();
        }
    });

    toggleAutoSubmitButton.addEventListener('click', () => {
        autoSubmitting = !autoSubmitting;
        toggleAutoSubmitButton.innerText = autoSubmitting ? '关闭自动提交' : '开启自动提交';
        toggleAutoSubmitButton.style.backgroundColor = autoSubmitting ? '#018786' : '#03DAC6';
        log(`自动提交功能已${autoSubmitting ? '开启' : '关闭'}`);
        if (autoSubmitting) {
            checkAndSubmit();
        }
    });


    function observeQuestions() {
        if (answerObserver) return; // 避免重复启动

        answerObserver = new MutationObserver(mutationCallback);
        answerObserver.observe(document.body, { childList: true, subtree: true });
        initialScanAnswer();
    }


    function disconnectAnswerObserver() {
        if (answerObserver) {
            answerObserver.disconnect();
            answerObserver = null;
        }
    }

    function initialScanAnswer() {
        log('执行初始扫描以查找现有问题');
        const questionNodes = document.querySelectorAll('.question-item:not([data-answered="true"])');
        log(`找到 ${questionNodes.length} 个未回答的问题节点`);
        questionNodes.forEach(node => {
            handleQuestionNode(node);
        });
    }


    function mutationCallback(mutationsList) {
        for (let mutation of mutationsList) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) { // 元素节点
                        if (node.classList.contains('question-item')) {
                            log('检测到新问题节点');
                            handleQuestionNode(node);
                        }
                        // 递归检查子节点
                        const questionChildren = node.querySelectorAll('.question-item');
                        questionChildren.forEach(child => {
                            log('检测到子问题节点');
                            handleQuestionNode(child);
                        });
                    }
                });
            }
        }
    }

    function hasIncompleteQuestions() {
        const incompleteDots = document.querySelectorAll('.index-dot-item-inner:not(.index-dot-item-inner-active)');
        return incompleteDots.length > 0;
    }


    function getIncompleteQuestionElements() {
        const incompleteDots = document.querySelectorAll('.index-dot-item-inner:not(.index-dot-item-inner-active)');
        let incompleteQuestions = [];

        incompleteDots.forEach(dot => {
            const questionNumber = dot.innerText.trim();
            if (questionNumber) {
                const questionElement = Array.from(document.querySelectorAll('.question-item')).find(item => {
                    const title = item.querySelector('.single-select-title, .multiple-select-title, .bol-select-title, .essay-select-title');
                    return title && title.innerText.includes(`${questionNumber}、`);
                });
                if (questionElement) {
                    incompleteQuestions.push(questionElement);
                } else {
                    log(`无法找到对应题号 ${questionNumber} 的问题元素`);
                }
            }
        });

        log(`找到 ${incompleteQuestions.length} 个未完成的问题元素`);
        return incompleteQuestions;
    }


    function handleQuestionNode(node) {
        if (node.getAttribute('data-answered') === 'true') {
            log('该问题已处理,跳过');
            return;
        }

        if (node.querySelector('.single-select-container')) {
            processSingleChoice(node);
        } else if (node.querySelector('.multiple-select-container')) {
            processMultipleChoice(node);
        } else if (node.querySelector('.bol-select-container')) {
            processTrueFalse(node);
        } else if (node.querySelector('.essay-select-container')) {
            processEssayQuestion(node);
        } else {
            log('检测到未知题型,停止自动化并等待用户手动处理');
            stopAnswerAutomation();
        }
    }


    function processSingleChoice(node) {
        const questionElement = node.querySelector('.single-select-title');
        if (!questionElement) {
            log('未找到单选题的问题文本元素');
            return;
        }
        const questionText = questionElement.innerText.trim();
        log(`处理单选题:${questionText}`);

        const optionsElements = node.querySelectorAll('.single-option-item');
        if (optionsElements.length === 0) {
            log('未找到单选题的选项元素');
            return;
        }

        let optionsText = '';
        let optionMap = {};

        optionsElements.forEach(option => {
            const indexElement = option.querySelector('.index');
            const titleElement = option.querySelector('.title');
            if (indexElement && titleElement) {
                const optionLetter = indexElement.innerText.trim();
                const optionContent = titleElement.innerText.trim();
                optionsText += `${optionLetter}. ${optionContent}\n`;
                optionMap[optionLetter.toUpperCase()] = option;
            } else {
                log('单选题的选项元素缺少 .index 或 .title 子元素');
            }
        });

        log(`构造的单选题选项文本:\n${optionsText}`);

        const prompt = `请根据以下问题选择一个最合适的答案,并仅回复答案的选项字母(如A、B、C或D),不要添加任何其他字符或符号:
问题:${questionText}
答案选项:
${optionsText}
回答:`;

        log(`发送API请求,提示语:\n${prompt}`);

        getAnswerFromAPI(prompt).then(answer => {
            log(`模型回答:${answer}`);
            const match = answer.toUpperCase().trim().match(/[A-D]/);
            if (match && match[0]) {
                const selectedLetter = match[0];
                log(`解析后的选项字母:${selectedLetter}`);

                if (optionMap[selectedLetter]) {
                    const selectedOption = optionMap[selectedLetter];
                    simulateClick(selectedOption);
                    log(`已尝试选择单选题的选项 ${selectedLetter}`);

                    setTimeout(() => {
                        const isSelected = selectedOption.classList.contains('selected') || selectedOption.classList.contains('active');
                        if (isSelected) {
                            log(`成功选择单选题的选项 ${selectedLetter}`);
                            node.setAttribute('data-answered', 'true');
                            markQuestionAsAnswered(selectedLetter);
                            if (autoSubmitting) {
                                setTimeout(() => checkAndSubmit(), 2000);
                            }
                        } else {
                            log(`未能成功选择单选题的选项 ${selectedLetter}`);
                        }
                    }, 1000);
                } else {
                    log(`模型返回的单选题选项字母无效或不存在:${selectedLetter}`);
                }
            } else {
                log(`无法解析模型返回的单选题答案:${answer}`);
            }
        }).catch(err => {
            log(`获取单选题答案时出错:${err}`);
        });
    }


    function processMultipleChoice(node) {
        const questionElement = node.querySelector('.multiple-select-title');
        if (!questionElement) {
            log('未找到多选题的问题文本元素');
            return;
        }
        const questionText = questionElement.innerText.trim();
        log(`处理多选题:${questionText}`);

        const optionsElements = node.querySelectorAll('.multiple-option-item');
        if (optionsElements.length === 0) {
            log('未找到多选题的选项元素');
            return;
        }

        let optionsText = '';
        let optionMap = {};

        optionsElements.forEach(option => {
            const indexElement = option.querySelector('.index');
            const titleElement = option.querySelector('.title');
            if (indexElement && titleElement) {
                const optionLetter = indexElement.innerText.trim();
                const optionContent = titleElement.innerText.trim();
                optionsText += `${optionLetter}. ${optionContent}\n`;
                optionMap[optionLetter.toUpperCase()] = option;
            } else {
                log('多选题的选项元素缺少 .index 或 .title 子元素');
            }
        });

        log(`构造的多选题选项文本:\n${optionsText}`);

        const prompt = `请根据以下问题选择所有合适的答案,并仅回复答案的选项字母,用逗号分隔(如A,B,C),不要添加任何其他字符或符号:
问题:${questionText}
答案选项:
${optionsText}
回答:`;

        log(`发送API请求,提示语:\n${prompt}`);

        getAnswerFromAPI(prompt).then(answer => {
            log(`模型回答:${answer}`);
            const matches = answer.toUpperCase().trim().match(/[A-D]/g);
            if (matches && matches.length > 0) {
                const selectedLetters = Array.from(new Set(matches));
                log(`解析后的多选题选项字母:${selectedLetters.join(',')}`);

                selectedLetters.forEach(letter => {
                    if (optionMap[letter]) {
                        const selectedOption = optionMap[letter];
                        simulateClick(selectedOption);
                        log(`已尝试选择多选题的选项 ${letter}`);
                    } else {
                        log(`模型返回的多选题选项字母无效或不存在:${letter}`);
                    }
                });

                setTimeout(() => {
                    let allSelected = true;
                    selectedLetters.forEach(letter => {
                        const option = optionMap[letter];
                        if (!option.classList.contains('selected') && !option.classList.contains('active')) {
                            allSelected = false;
                            log(`未能成功选择多选题的选项 ${letter}`);
                        }
                    });

                    if (allSelected) {
                        log(`成功选择多选题的选项 ${selectedLetters.join(',')}`);
                        node.setAttribute('data-answered', 'true');
                        markMultipleQuestionsAsAnswered(selectedLetters);
                        if (autoSubmitting) {
                            setTimeout(() => checkAndSubmit(), 2000);
                        }
                    } else {
                        log(`部分多选题选项未能成功选择`);
                    }
                }, 1000);
            } else {
                log(`无法解析模型返回的多选题答案:${answer}`);
            }
        }).catch(err => {
            log(`获取多选题答案时出错:${err}`);
        });
    }


    function processTrueFalse(node) {
        const questionElement = node.querySelector('.bol-select-title');
        if (!questionElement) {
            log('未找到判断题的问题文本元素');
            return;
        }
        const questionText = questionElement.innerText.trim();
        log(`处理判断题:${questionText}`);

        const optionsElements = node.querySelectorAll('.bol-option-item');
        if (optionsElements.length !== 2) {
            log('判断题应有两个选项,跳过');
            return;
        }

        let optionsText = '';
        let optionMap = {};

        optionsElements.forEach(option => {
            const titleElement = option.querySelector('.title');
            if (titleElement) {
                const optionContent = titleElement.innerText.trim();
                optionsText += `${optionContent}\n`;
                optionMap[optionContent.toLowerCase()] = option;
            } else {
                log('选项元素缺少 .title 子元素');
            }
        });

        log(`构造的选项文本:\n${optionsText}`);

        const prompt = `请根据以下判断题选择一个最合适的答案,并仅回复答案的选项文本(如“对”或“错”),不要添加任何其他字符或符号:
问题:${questionText}
答案选项:
${optionsText}
回答:`;

        log(`发送API请求,提示语:\n${prompt}`);

        getAnswerFromAPI(prompt).then(answer => {
            log(`模型回答:${answer}`);
            const match = answer.trim().match(/^(对|错)$/i);
            if (match && match[1]) {
                const selectedText = match[1].toLowerCase();
                log(`解析后的选项文本:${selectedText}`);

                if (optionMap[selectedText]) {
                    const selectedOption = optionMap[selectedText];
                    simulateClick(selectedOption);
                    log(`已尝试选择选项 ${selectedText}`);

                    setTimeout(() => {
                        const isSelected = selectedOption.classList.contains('selected') || selectedOption.classList.contains('active');
                        if (isSelected) {
                            log(`成功选择选项 ${selectedText}`);
                            node.setAttribute('data-answered', 'true');
                            markTrueFalseQuestionAsAnswered(selectedText);
                            if (autoSubmitting) {
                                setTimeout(() => checkAndSubmit(), 2000);
                            }
                        } else {
                            log(`未能成功选择选项 ${selectedText}`);
                        }
                    }, 1000);
                } else {
                    log(`模型返回的选项文本无效或不存在:${selectedText}`);
                }
            } else {
                log(`无法解析模型返回的答案:${answer}`);
            }
        }).catch(err => {
            log(`获取答案时出错:${err}`);
        });
    }


    function processEssayQuestion(node) {
        const questionElement = node.querySelector('.essay-select-title');
        if (!questionElement) {
            log('未找到论述题的问题文本元素');
            return;
        }
        const questionText = questionElement.innerText.trim();
        log(`处理论述题:${questionText}`);

        const textareaElement = node.querySelector('.essay-option-item textarea');
        if (!textareaElement) {
            log('未找到论述题的文本区域');
            return;
        }

        const saveButton = node.querySelector('.submit-inner-box');

        const prompt = `请根据以下论述题提供一个详细且全面的回答,确保回答清晰、有逻辑并涵盖所有关键点:
问题:${questionText}
回答:`;

        log(`发送API请求,提示语:\n${prompt}`);

        getAnswerFromAPI(prompt).then(answer => {
            log(`模型回答:${answer}`);
            fillAnswer(textareaElement, answer);
            node.setAttribute('data-answered', 'true');
            log('已填充答案并标记任务为已处理');
            if (autoSave) {
                saveAnswer(saveButton, node);
            }
            if (autoSubmitting) {
                setTimeout(() => checkAndSubmit(), 5000);
            }
        }).catch(err => {
            log(`获取论述题答案时出错:${err}`);
        });
    }


    function simulateClick(optionElement) {
        const titleElement = optionElement.querySelector('.index, .title');
        if (titleElement) {
            const events = ['mousedown', 'mouseup', 'click'];
            events.forEach(eventType => {
                const event = new MouseEvent(eventType, {
                    view: window,
                    bubbles: true,
                    cancelable: true
                });
                titleElement.dispatchEvent(event);
            });
            log(`已模拟点击选项标题`);
        } else {
            log('未找到选项标题元素,无法模拟点击');
        }
    }


    async function getAnswerFromAPI(prompt) {
        const options = {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${API_KEY}`,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                model: MODEL,
                messages: [
                    { role: 'user', content: prompt }
                ],
                stream: false,
                max_tokens: MAX_TOKENS
            })
        };

        try {
            const response = await fetch(API_URL, options);
            if (!response.ok) {
                throw new Error(`API请求失败,状态码:${response.status}`);
            }

            const data = await response.json();
            if (data.choices && data.choices.length > 0 && data.choices[0].message && data.choices[0].message.content) {
                const answer = data.choices[0].message.content.trim();
                return answer;
            } else {
                throw new Error('API返回的数据格式不正确');
            }
        } catch (error) {
            log(`API调用出错:${error.message}`);
            throw error;
        }
    }


    function submitAnswers() {
        const submitButton = document.querySelector('.submit-button, .submit-btn, .confirm-btn');
        if (submitButton) {
            const isDisabled = submitButton.disabled || submitButton.classList.contains('disabled');
            if (!isDisabled) {
                submitButton.click();
                log('已自动点击初始提交按钮');
                handleConfirmationModal();
                setupSubmissionErrorObserver();
            } else {
                log('提交按钮被禁用,开始轮询等待提交条件满足');
                waitAndSubmit();
            }
        } else {
            log('未找到提交按钮');
        }
    }


    function handleConfirmationModal() {
        const modalCheckInterval = 1000;
        const maxModalRetries = 10;
        let modalAttempts = 0;

        const modalIntervalId = setInterval(() => {
            const confirmButton = document.querySelector('.ant-modal-content .ant-modal-confirm-btns .ant-btn-primary');
            if (confirmButton) {
                confirmButton.click();
                log('已自动点击确认模态框的提交按钮');
                clearInterval(modalIntervalId);
            } else {
                modalAttempts++;
                log(`未找到确认模态框的提交按钮,已尝试 ${modalAttempts} 次`);
                if (modalAttempts >= maxModalRetries) {
                    log('未能找到确认模态框的提交按钮,停止尝试');
                    clearInterval(modalIntervalId);
                }
            }
        }, modalCheckInterval);
    }


    function waitAndSubmit() {
        const retryInterval = 5000;
        const maxRetries = 12;
        let attempts = 0;

        const intervalId = setInterval(() => {
            const submitButton = document.querySelector('.submit-button, .submit-btn, .confirm-btn');
            if (submitButton && !submitButton.disabled && !submitButton.classList.contains('disabled')) {
                submitButton.click();
                log('已自动点击提交按钮');
                handleConfirmationModal();
                setupSubmissionErrorObserver();
                clearInterval(intervalId);
            } else {
                attempts++;
                log(`提交按钮仍不可用,已尝试 ${attempts} 次`);
                if (attempts >= maxRetries) {
                    log('达到最大重试次数,停止轮询提交');
                    clearInterval(intervalId);
                }
            }
        }, retryInterval);
    }


    function stopAnswerAutomation() {
        answering = false;
        completing = false;
        disconnectAnswerObserver();
        disconnectCompleteObserver();
        startAnswerButton.innerText = '开始自动完成';
        startAnswerButton.style.backgroundColor = '#6200EE';
        startCompleteButton.innerText = '开始自动完成';
        startCompleteButton.style.backgroundColor = '#03A9F4';
        toggleAutoSubmitButton.innerText = '开启自动提交';
        toggleAutoSubmitButton.style.backgroundColor = '#03DAC6';
        toggleAutoSaveButton.innerText = '开启自动保存';
        toggleAutoSaveButton.style.backgroundColor = '#FF9800';
        alert('检测到未知题型,自动化已停止。请手动提交并处理这些题目。');
        log('检测到未知题型,自动化已停止。');
    }


    function markQuestionAsAnswered(selectedLetter) {
        const questionElement = Array.from(document.querySelectorAll('.question-item')).find(item => {
            const title = item.querySelector('.single-select-title, .multiple-select-title, .bol-select-title, .essay-select-title');
            return title && title.innerText.includes(`${selectedLetter}、`);
        });

        if (questionElement) {
            const questionNumberMatch = questionElement.querySelector('.single-select-title, .multiple-select-title, .bol-select-title, .essay-select-title').innerText.match(/(\d+)、/);
            if (questionNumberMatch && questionNumberMatch[1]) {
                const questionNumber = questionNumberMatch[1];
                const dotElement = Array.from(document.querySelectorAll('.index-dot-item-inner')).find(dot => dot.innerText.trim() === questionNumber);
                if (dotElement) {
                    dotElement.classList.add('index-dot-item-inner-active');
                    log(`已标记题号 ${questionNumber} 为已完成`);
                }
            }
        }
    }


    function markMultipleQuestionsAsAnswered(selectedLetters) {
        selectedLetters.forEach(letter => {
            markQuestionAsAnswered(letter);
        });
    }


    function markTrueFalseQuestionAsAnswered(selectedText) {
        const questionElement = Array.from(document.querySelectorAll('.question-item')).find(item => {
            const title = item.querySelector('.bol-select-title');
            return title && title.innerText.includes(selectedText === '对' ? '对' : '错');
        });

        if (questionElement) {
            const questionNumberMatch = questionElement.querySelector('.bol-select-title').innerText.match(/(\d+)、/);
            if (questionNumberMatch && questionNumberMatch[1]) {
                const questionNumber = questionNumberMatch[1];
                const dotElement = Array.from(document.querySelectorAll('.index-dot-item-inner')).find(dot => dot.innerText.trim() === questionNumber);
                if (dotElement) {
                    dotElement.classList.add('index-dot-item-inner-active');
                    log(`已标记判断题号 ${questionNumber} 为已完成`);
                }
            }
        }
    }


    function markEssayQuestionAsAnswered(questionNumber) {
        const dotElement = Array.from(document.querySelectorAll('.index-dot-item-inner')).find(dot => dot.innerText.trim() === questionNumber);
        if (dotElement) {
            dotElement.classList.add('index-dot-item-inner-active');
            log(`已标记论述题号 ${questionNumber} 为已完成`);
        }
    }


    function checkAndSubmit() {
        if (hasIncompleteQuestions()) {
            log('存在未完成的题目,准备回答这些题目');
            const incompleteQuestions = getIncompleteQuestionElements();
            if (incompleteQuestions.length > 0) {
                incompleteQuestions.forEach(question => {
                    handleQuestionNode(question);
                });
                setTimeout(() => {
                    checkAndSubmit();
                }, 3000);
            }
        } else {
            log('所有题目已完成,准备提交');
            submitAnswers();
        }
    }


    function setupSubmissionErrorObserver() {
        const messageContainer = document.querySelector('.ant-message');
        if (!messageContainer) {
            log('未找到消息容器,无法设置错误消息观察器');
            return;
        }

        const errorObserver = new MutationObserver((mutationsList) => {
            for (let mutation of mutationsList) {
                if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1) {
                            const errorSpan = node.querySelector('.ant-message-error span');
                            if (errorSpan) {
                                const errorText = errorSpan.innerText;
                                log(`检测到提交错误消息:${errorText}`);
                                const match = errorText.match(/最小提交作答时间为(\d+)分钟/);
                                if (match && match[1]) {
                                    const waitMinutes = parseInt(match[1], 10);
                                    const waitMilliseconds = waitMinutes * 60 * 1000;
                                    log(`需要等待 ${waitMinutes} 分钟后再提交`);
                                    submitRetryCount++;
                                    if (submitRetryCount > MAX_SUBMIT_RETRIES) {
                                        log('已达到最大提交重试次数,停止自动提交');
                                        errorObserver.disconnect();
                                        return;
                                    }
                                    setTimeout(() => {
                                        log('等待时间已到,重新尝试提交');
                                        submitAnswers();
                                    }, waitMilliseconds);
                                } else {
                                    log('无法解析等待时间,停止自动提交');
                                }
                            }
                        }
                    });
                }
            }
        });

        const config = { childList: true, subtree: true };
        errorObserver.observe(messageContainer, config);
        log('已设置提交错误消息观察器');
    }



    startCompleteButton.addEventListener('click', () => {
        if (!completing) {
            completing = true;
            startCompleteButton.innerText = '停止自动完成';
            startCompleteButton.style.backgroundColor = '#0288D1';
            log('开始自动完成作业');
            observeTextTasks();

            if (autoSave) {
                setTimeout(() => {
                    checkAndSubmit();
                }, 1000);
            }
        } else {
            completing = false;
            startCompleteButton.innerText = '开始自动完成';
            startCompleteButton.style.backgroundColor = '#03A9F4';
            log('停止自动完成作业');
            disconnectCompleteObserver();
        }
    });


    toggleAutoSaveButton.addEventListener('click', () => {
        autoSave = !autoSave;
        toggleAutoSaveButton.innerText = autoSave ? '关闭自动保存' : '开启自动保存';
        toggleAutoSaveButton.style.backgroundColor = autoSave ? '#F57C00' : '#FF9800';
        log(`自动点击保存功能已${autoSave ? '开启' : '关闭'}`);

        if (autoSave && completing) {
            checkAndSubmit();
        }
    });


    function observeTextTasks() {
        if (completeObserver) return;
        completeObserver = new MutationObserver(mutationCallbackComplete);
        completeObserver.observe(document.body, { childList: true, subtree: true });
        initialScanComplete();
    }


    function disconnectCompleteObserver() {
        if (completeObserver) {
            completeObserver.disconnect();
            completeObserver = null;
        }
    }


    function initialScanComplete() {
        log('执行初始扫描以查找现有的文本任务');
        const textTaskNodes = document.querySelectorAll('.question-container:not([data-processed="true"])');
        log(`找到 ${textTaskNodes.length} 个未处理的文本任务节点`);
        textTaskNodes.forEach(node => {
            handleTextTaskNode(node);
        });
    }


    function mutationCallbackComplete(mutationsList) {
        for (let mutation of mutationsList) {
            if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
                mutation.addedNodes.forEach(node => {
                    if (node.nodeType === 1) { // 元素节点
                        if (node.classList.contains('question-container')) {
                            log('检测到新文本任务节点');
                            handleTextTaskNode(node);
                        }

                        const textTaskChildren = node.querySelectorAll('.question-container');
                        textTaskChildren.forEach(child => {
                            log('检测到子文本任务节点');
                            handleTextTaskNode(child);
                        });
                    }
                });
            }
        }
    }


    function getIncompleteTextTaskElements() {
        const incompleteTasks = document.querySelectorAll('.question-container:not([data-processed="true"])');
        log(`找到 ${incompleteTasks.length} 个未完成的文本任务元素`);
        return Array.from(incompleteTasks);
    }


    function handleTextTaskNode(node) {
        if (node.getAttribute('data-processed') === 'true') {
            log('该文本任务已处理,跳过');
            return;
        }

        const titleElement = node.querySelector('.question-title');
        const contentElement = node.querySelector('.announce-box .text-box p');
        const editorElement = node.querySelector('.editor-box [contenteditable="true"]');
        const saveButton = node.querySelector('.submit-inner-box');

        if (!titleElement || !contentElement || !editorElement || !saveButton) {
            log('未找到完整的文本任务元素,跳过');
            return;
        }

        const taskTitle = titleElement.innerText.trim();
        const taskContent = contentElement.innerText.trim();
        log(`处理文本任务:${taskTitle} - ${taskContent}`);

        const prompt = `请根据以下任务内容完成作答,并直接返回答案文本,不要添加任何额外的解释或内容:
任务标题:${taskTitle}
任务内容:${taskContent}
答案:`;

        log(`发送API请求,提示语:\n${prompt}`);

        getAnswerFromAPI(prompt).then(answer => {
            log(`模型回答:${answer}`);
            fillAnswer(editorElement, answer);
            node.setAttribute('data-processed', 'true');
            log('已填充答案并标记任务为已处理');
            if (autoSave) {
                saveAnswer(saveButton, node);
            }

            if (autoSave) {
                setTimeout(() => {
                    checkAndSubmit();
                }, 1000);
            }
        }).catch(err => {
            log(`获取答案时出错:${err}`);
        });
    }


    function fillAnswer(editorElement, answer) {
        editorElement.focus();
        editorElement.innerHTML = '';
        editorElement.innerText = answer;
        log('已将答案填充到编辑器');

        const inputEvent = new Event('input', { bubbles: true });
        editorElement.dispatchEvent(inputEvent);
    }


    function saveAnswer(saveButton, node) {
        if (saveButton) {
            saveButton.click();
            log('已自动点击保存按钮');
            // 立即尝试提交
            setTimeout(() => {
                checkAndSubmit();
            }, 1000);
        } else {
            log('未找到保存按钮,无法自动点击');
        }
    }


    window.addEventListener('load', () => {
        log('页面加载完成,准备初始化脚本');
        if (answering) {
            observeQuestions();
        }
        if (completing) {
            observeTextTasks();
        }
    });

})();