Greasy Fork

Greasy Fork is available in English.

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

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

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         重庆高等教育智慧教育平台学习助手 || cqooc重庆高等教育智慧教育平台学习助手 || www.cqooc.com
// @namespace    http://tampermonkey.net/
// @version      4.3
// @description  1.看说明就行了。2.反对任何形式牟利,祝各位同学学有所成。3.更新了作业测验作答 4.反馈群:1006332809
// @author       Abstract
// @include      https://*.cqooc.com/*
// @include      https://*.*.smartedu.cn/*
// @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
// @require      https://unpkg.com/vue@3/dist/vue.global.js
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // ===============================
    // 常量定义
    // ===============================

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

    // Vue API 变量(稍后初始化)
    let createApp, ref, computed, onMounted, reactive;

    const COMPLETION_STATUSES = {
        '未完成': '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 CATEGORY_KEYWORDS = {
        '测验': ['测验', '测试'],
        '课件': ['课件', '小节', '视频'],
        '作业': ['作业'],
        '讨论': ['讨论', '答疑'],
        '考试': ['考试', '期末测试', '补考'],
        '其他': []
    };

    // ===============================
    // 工具函数
    // ===============================

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

    async function waitForElement(selector, timeout = 5000) {
        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 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));
                }
            }
        }
    }

    // ===============================
    // Vue 3 Composition API 组合函数
    // ===============================

    // 等待内容加载
    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');
                console.log('[学习助手] 等待课件加载...', items.length, '个元素');
                if (items.length > 0 || retries >= maxRetries) {
                    clearInterval(interval);
                    resolve(items.length);
                }
                retries++;
            }, intervalTime);
        });
    }

    // 课程扫描组合函数
    function useCourseScanner() {
        const allCourses = ref([]);
        const currentCourse = ref(null);
        const isScanning = ref(false);

        // 扫描所有课件
        const scanAllCourses = async () => {
            isScanning.value = true;
            console.log('[学习助手] 开始扫描课件...');

            // 等待内容加载
            const count = await waitForContentLoaded();
            console.log('[学习助手] 内容加载完成,找到', count, '个元素');

            const courseElements = document.querySelectorAll('.third-level-inner-box');
            const courses = [];

            // 用于处理同名课件的计数器
            const titleCountMap = {};

            let index = 0;
            for (const element of courseElements) {
                const titleElement = element.querySelector('p.title, p.title-big');
                if (!titleElement) continue;

                const titleText = titleElement.textContent.trim();
                let category = '其他';

                // 分类课件
                for (const [cat, keywords] of Object.entries(CATEGORY_KEYWORDS)) {
                    if (keywords.some(keyword => titleText.includes(keyword))) {
                        category = cat;
                        break;
                    }
                }

                // 检查完成状态
                let status = '未完成';
                const img = element.querySelector('img.file-complete');
                if (img) {
                    const src = img.getAttribute('src');
                    if (src === COMPLETION_STATUSES['已完成']) {
                        status = '已完成';
                    } else if (src === COMPLETION_STATUSES['半完成']) {
                        status = '半完成';
                    } else if (src === COMPLETION_STATUSES['未完成']) {
                        status = '未完成';
                    }
                }

                // 处理同名课件:给每个同名课件分配序号
                if (!titleCountMap[titleText]) {
                    titleCountMap[titleText] = 0;
                }
                titleCountMap[titleText]++;
                const titleIndex = titleCountMap[titleText];

                // 生成唯一ID:使用DOM索引
                const uniqueId = 'course_' + index;

                // 检查讨论回复状态(从localStorage读取)
                let replyStatus = '未回复';
                if (category === '讨论') {
                    try {
                        const replied = JSON.parse(localStorage.getItem('repliedDiscussions') || '[]');
                        if (replied.includes(titleText)) {
                            replyStatus = '已回复';
                        }
                    } catch {}
                }

                courses.push({
                    element,
                    title: titleText,
                    titleIndex: titleIndex,  // 同名课件的序号(1, 2, 3...)
                    uniqueId: uniqueId,      // 唯一ID
                    domIndex: index,         // DOM索引
                    category,
                    status,
                    isCompleted: status === '已完成',
                    replyStatus: replyStatus  // 讨论回复状态
                });

                index++;
            }

            allCourses.value = courses;
            isScanning.value = false;
            console.log('[学习助手] 扫描完成,共', courses.length, '个课件');
        };

        // 获取下一个未完成课件
        const getNextUncompletedCourse = () => {
            return allCourses.value.find(course => !course.isCompleted);
        };

        // 统计信息(只统计课件类型)
        const statistics = computed(() => {
            const coursewareOnly = allCourses.value.filter(c => c.category === '课件');
            const total = coursewareOnly.length;
            const completed = coursewareOnly.filter(c => c.isCompleted).length;
            const remaining = total - completed;

            return { total, completed, remaining };
        });

        // 按分类获取课件
        const getCoursesByCategory = (category) => {
            return allCourses.value.filter(c => c.category === category);
        };

        return {
            allCourses,
            currentCourse,
            isScanning,
            scanAllCourses,
            getNextUncompletedCourse,
            getCoursesByCategory,
            statistics
        };
    }

    // 自动学习组合函数(队列模式)
    function useAutoLearning() {
        const isLearning = ref(false);
        const currentTask = ref('');
        const progress = ref(0);

        // 队列相关状态
        const courseQueue = ref([]);           // 未完成课件队列
        const queueIndex = ref(0);             // 当前处理索引
        const completedCount = ref(0);         // 本轮完成数量
        const failCount = ref(0);              // 连续失败计数
        const totalProcessed = ref(0);         // 总处理数量(用于定期刷新)
        const shouldStop = ref(false);         // 停止标志

        // 配置
        const CONFIG = {
            REFRESH_EVERY_N: 10,               // 每处理N个课件刷新一次
            MAX_CONTINUOUS_FAIL: 3,            // 连续失败N次后刷新
            WAIT_AFTER_403: 5 * 60 * 1000,     // 403后等待时间(5分钟)
            RETRY_DELAY: 2000,                 // 重试延迟
        };

        // 通过DOM索引查找课件元素(处理同名课件问题)
        const findCourseElementByIndex = (domIndex) => {
            const allItems = document.querySelectorAll('.third-level-inner-box');
            if (domIndex >= 0 && domIndex < allItems.length) {
                return allItems[domIndex];
            }
            return null;
        };

        // 通过标题和序号查找课件元素(备用方案)
        const findCourseElementByTitleAndIndex = (title, titleIndex) => {
            const allItems = document.querySelectorAll('.third-level-inner-box');
            let matchCount = 0;
            for (const item of allItems) {
                const titleEl = item.querySelector('p.title, p.title-big');
                if (titleEl && titleEl.textContent.trim() === title) {
                    matchCount++;
                    if (matchCount === titleIndex) {
                        return item;
                    }
                }
            }
            return null;
        };

        // 刷新课件的element引用(使用DOM索引)
        const refreshCourseElement = (courseData) => {
            // 优先使用DOM索引查找
            let newElement = findCourseElementByIndex(courseData.domIndex);

            // 如果DOM索引失效,尝试用标题+序号查找
            if (!newElement && courseData.titleIndex) {
                newElement = findCourseElementByTitleAndIndex(courseData.title, courseData.titleIndex);
            }

            if (newElement) {
                courseData.element = newElement;
                return true;
            }
            console.log('[学习助手] 找不到课件元素:', courseData.title, '索引:', courseData.domIndex);
            return false;
        };

        // 检查课件当前是否已完成(使用DOM索引)
        const isCourseCompleted = (courseData) => {
            // 先刷新element引用
            if (!refreshCourseElement(courseData)) {
                return false; // 找不到元素,不能判断为已完成
            }

            const img = courseData.element.querySelector('img.file-complete');
            if (img) {
                const src = img.getAttribute('src');
                return src === COMPLETION_STATUSES['已完成'];
            }
            return false;
        };

        // 获取课件当前的图标src(使用DOM索引)
        const getCourseIconSrc = (courseData) => {
            if (!refreshCourseElement(courseData)) {
                return null;
            }
            const img = courseData.element.querySelector('img.file-complete');
            if (img) {
                return img.getAttribute('src');
            }
            return null;
        };

        // 跳转到课件(带重试)
        const jumpToCourse = async (courseData, retryCount = 2) => {
            for (let i = 0; i <= retryCount; i++) {
                try {
                    // 每次跳转前刷新element引用
                    if (!refreshCourseElement(courseData)) {
                        console.log('[学习助手] 找不到课件元素:', courseData.title);
                        if (i < retryCount) {
                            await new Promise(resolve => setTimeout(resolve, CONFIG.RETRY_DELAY));
                            continue;
                        }
                        return false;
                    }

                    await expandAllParentsAsync(courseData.element);
                    const clickable = courseData.element.querySelector('a') ||
                          courseData.element.querySelector('p.title') ||
                          courseData.element;

                    if (clickable) {
                        clickable.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        await new Promise(resolve => setTimeout(resolve, 500));
                        simulateClick(clickable);
                        return true;
                    }
                } catch (error) {
                    console.error('[学习助手] 跳转失败(尝试' + (i+1) + '):', error);
                    if (i < retryCount) {
                        await new Promise(resolve => setTimeout(resolve, CONFIG.RETRY_DELAY));
                    }
                }
            }
            return false;
        };

        // 等待图标变成已完成状态
        const waitForCompletionIcon = async (courseData, maxWaitTime = 15000) => {
            return new Promise((resolve) => {
                const startTime = Date.now();
                const originalSrc = courseData.originalSrc;

                console.log('[学习助手] 开始检测图标变化,课件:', courseData.title, '索引:', courseData.domIndex);

                const checkInterval = setInterval(() => {
                    const currentSrc = getCourseIconSrc(courseData);

                    if (currentSrc) {
                        if (currentSrc !== originalSrc && currentSrc === COMPLETION_STATUSES['已完成']) {
                            clearInterval(checkInterval);
                            console.log('[学习助手] 检测到图标变为已完成');
                            resolve(true);
                            return;
                        }

                        if (originalSrc === COMPLETION_STATUSES['已完成']) {
                            clearInterval(checkInterval);
                            console.log('[学习助手] 课件原本就是已完成状态');
                            resolve(true);
                            return;
                        }
                    }

                    const elapsed = Date.now() - startTime;
                    if (elapsed > maxWaitTime) {
                        clearInterval(checkInterval);
                        console.log('[学习助手] 等待图标超时');
                        resolve(false);
                    }
                }, 2000);
            });
        };

        // 处理视频(传入courseData包含title和originalSrc)
        const handleVideo = async (video, courseData) => {
            return new Promise(async (resolve) => {
                currentTask.value = '正在播放视频: ' + courseData.title;

                try {
                    video.muted = true;
                    video.autoplay = true;
                    video.playsInline = true;

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

                    const onTimeUpdate = () => {
                        if (!video.duration) return;
                        const currentProgress = (video.currentTime / video.duration) * 100;
                        progress.value = Math.floor(currentProgress);

                        if (currentProgress >= 99.9) {
                            video.removeEventListener('timeupdate', onTimeUpdate);
                            currentTask.value = '视频播放完成,等待确认...';

                            // 等待图标变化确认完成(传入完整courseData)
                            waitForCompletionIcon(courseData).then(() => {
                                resolve();
                            });
                        }
                    };

                    video.addEventListener('loadedmetadata', applyPlaybackRate, { once: true });
                    video.addEventListener('canplay', applyPlaybackRate, { once: true });
                    video.addEventListener('timeupdate', onTimeUpdate);

                    await video.play();
                    applyPlaybackRate();

                } catch (error) {
                    console.error('视频播放错误:', error);
                    resolve();
                }
            });
        };

        // 获取主页面倒计时秒数(更精确定位)
        const getCountdownSeconds = () => {
            // 优先查找带红色样式的倒计时元素
            const allElements = document.querySelectorAll('div');
            for (const el of allElements) {
                const text = el.textContent || '';
                // 匹配 "完成倒计时:XXs" 或 "完成倒计时:XXs"
                const match = text.match(/完成倒计时[::]\s*(\d+)s/);
                if (match) {
                    // 检查是否是直接包含倒计时文本的元素(避免获取父元素的文本)
                    if (el.childElementCount === 0 || el.innerText.includes('完成倒计时')) {
                        return parseInt(match[1], 10);
                    }
                }
            }
            return 0;
        };

        // 等待主页面倒计时结束
        const waitForCountdownEnd = () => {
            return new Promise((resolve) => {
                const initialSeconds = getCountdownSeconds();
                if (initialSeconds <= 0) {
                    console.log('[学习助手] 无倒计时,直接继续');
                    resolve();
                    return;
                }

                console.log('[学习助手] 检测到完成倒计时:', initialSeconds, '秒,开始等待...');
                currentTask.value = '等待完成倒计时: ' + initialSeconds + 's';

                let lastSeconds = initialSeconds;
                let sameValueCount = 0;  // 连续相同值计数
                let timeoutId = null;

                const countdownInterval = setInterval(() => {
                    const seconds = getCountdownSeconds();
                    console.log('[学习助手] 倒计时剩余:', seconds, '秒');
                    currentTask.value = '等待完成倒计时: ' + seconds + 's';

                    // 检测倒计时是否结束
                    if (seconds <= 0) {
                        clearInterval(countdownInterval);
                        if (timeoutId) clearTimeout(timeoutId);
                        console.log('[学习助手] 倒计时结束,等待2秒后继续');
                        currentTask.value = '倒计时结束,等待确认...';
                        setTimeout(() => {
                            resolve();
                        }, 2000);
                        return;
                    }

                    // 检测倒计时是否卡住(连续5次相同值)
                    if (seconds === lastSeconds) {
                        sameValueCount++;
                        if (sameValueCount >= 5) {
                            clearInterval(countdownInterval);
                            if (timeoutId) clearTimeout(timeoutId);
                            console.log('[学习助手] 倒计时卡住,强制继续');
                            currentTask.value = '倒计时异常,继续...';
                            setTimeout(() => {
                                resolve();
                            }, 2000);
                            return;
                        }
                    } else {
                        sameValueCount = 0;
                        lastSeconds = seconds;
                    }
                }, 1000);

                // 倒计时超时保护(3分钟)
                timeoutId = setTimeout(() => {
                    clearInterval(countdownInterval);
                    console.log('[学习助手] 倒计时等待超时');
                    resolve();
                }, 180000);
            });
        };

        // 处理PPT(通过监听iframe的postMessage来判断完成)
        const handlePPT = async (courseData) => {
            return new Promise((resolve) => {
                currentTask.value = '正在播放PPT: ' + courseData.title;
                console.log('[学习助手] 开始处理PPT,等待iframe完成消息...');

                let hasReportedCompletion = false;
                let progressCheckInterval = null;
                let isScrollTypePPT = false;  // 是否是滚轮式PPT(PDF预览)

                // PPT翻页完成后的处理(检查倒计时)
                const onPptPagesFinished = async () => {
                    console.log('[学习助手] PPT翻页完成,检查是否有倒计时...');
                    currentTask.value = 'PPT翻页完成,检查倒计时...';

                    // 等待倒计时结束(如果有的话)
                    await waitForCountdownEnd();

                    // 等待图标变化确认完成
                    currentTask.value = 'PPT播放完成,等待图标确认...';
                    await waitForCompletionIcon(courseData);
                    resolve();
                };

                // 监听iframe发来的完成消息
                const messageHandler = (event) => {
                    if (!event.origin.includes('cqooc.com')) return;
                    const data = event.data;
                    if (!data || !data.type) return;

                    if (data.type === 'pptCompleted' && !hasReportedCompletion) {
                        hasReportedCompletion = true;
                        console.log('[学习助手] 收到PPT完成消息');
                        window.removeEventListener('message', messageHandler);
                        if (progressCheckInterval) clearInterval(progressCheckInterval);
                        progress.value = 100;

                        onPptPagesFinished();
                    } else if (data.type === 'pptProgress') {
                        progress.value = Math.floor(data.progress || 0);
                    }
                };

                window.addEventListener('message', messageHandler);

                // 检测是否是滚轮式PPT(无翻页按钮无进度条)
                setTimeout(() => {
                    const progressBar = document.querySelector('.bottom-paging-progress .bar');
                    const nextButton = document.querySelector('.slide-img-container.context-menu-disabled .ppt-turn-right-mask');

                    if (!progressBar && !nextButton) {
                        // 滚轮式PPT(PDF预览),只需等待倒计时
                        isScrollTypePPT = true;
                        console.log('[学习助手] 检测到滚轮式PPT/PDF,只等待倒计时...');
                        currentTask.value = '滚轮式PPT/PDF,等待倒计时...';

                        // 直接等待倒计时结束
                        if (!hasReportedCompletion) {
                            hasReportedCompletion = true;
                            window.removeEventListener('message', messageHandler);
                            if (progressCheckInterval) clearInterval(progressCheckInterval);

                            waitForCountdownEnd().then(() => {
                                currentTask.value = '倒计时结束,等待图标确认...';
                                return waitForCompletionIcon(courseData);
                            }).then(() => {
                                resolve();
                            });
                        }
                    }
                }, 3000);

                // 同时也尝试检测主页面上的进度条(备用方案)
                progressCheckInterval = setInterval(() => {
                    if (isScrollTypePPT) return;  // 滚轮式PPT不需要检测进度

                    const progressBar = document.querySelector('.bottom-paging-progress .bar');
                    if (progressBar) {
                        let width = parseFloat(progressBar.style.width) || 0;
                        progress.value = Math.floor(width);

                        // 尝试点击下一页按钮
                        const nextButton = document.querySelector('.slide-img-container.context-menu-disabled .ppt-turn-right-mask');
                        if (width < 100 && nextButton) {
                            simulateClick(nextButton);
                        }

                        if (width >= 100 && !hasReportedCompletion) {
                            hasReportedCompletion = true;
                            console.log('[学习助手] 检测到PPT进度100%');
                            window.removeEventListener('message', messageHandler);
                            clearInterval(progressCheckInterval);

                            onPptPagesFinished();
                        }
                    }
                }, 1000);

                // 超时处理(3分钟,考虑倒计时)
                setTimeout(() => {
                    if (!hasReportedCompletion) {
                        hasReportedCompletion = true;
                        console.log('[学习助手] PPT处理超时');
                        window.removeEventListener('message', messageHandler);
                        if (progressCheckInterval) clearInterval(progressCheckInterval);

                        currentTask.value = 'PPT处理超时,等待确认...';
                        waitForCompletionIcon(courseData).then(() => {
                            resolve();
                        });
                    }
                }, 180000);
            });
        };

        // 等待元素出现的辅助函数
        const waitForElementWithTimeout = async (selector, timeout = 10000) => {
            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);
                    }
                }, 500);
            });
        };

        // 检测是否有PPT的iframe
        const detectPPTIframe = () => {
            const iframes = document.querySelectorAll('iframe');
            for (const iframe of iframes) {
                if (iframe.src && iframe.src.includes('preview.cqooc.com')) {
                    return iframe;
                }
            }
            return null;
        };

        // 处理单个课件(返回: 'success' | 'fail' | 'skip' | 'error')
        const processSingleCourse = async (courseData) => {
            progress.value = 0;

            // 先检查是否已完成(可能被其他方式完成了)
            if (isCourseCompleted(courseData)) {
                console.log('[学习助手] 课件已完成,跳过:', courseData.title, '索引:', courseData.domIndex);
                currentTask.value = '课件已完成,跳过';
                return 'skip';
            }

            // 记录原始图标状态
            const originalSrc = getCourseIconSrc(courseData);
            courseData.originalSrc = originalSrc;
            console.log('[学习助手] 开始处理课件:', courseData.title, '索引:', courseData.domIndex);

            // 跳转到课件
            const jumpSuccess = await jumpToCourse(courseData);
            if (!jumpSuccess) {
                console.log('[学习助手] 跳转失败:', courseData.title);
                return 'fail';
            }

            // 等待页面加载
            await new Promise(resolve => setTimeout(resolve, 3000));

            // 检查课件类型并处理
            if (courseData.category === '课件') {
                currentTask.value = '正在检测课件类型...';

                const pptIframe = detectPPTIframe();
                if (pptIframe) {
                    console.log('[学习助手] 检测到PPT iframe');
                    await handlePPT(courseData);
                } else {
                    console.log('[学习助手] 等待视频元素...');
                    const video = await waitForElementWithTimeout('.dplayer-video-wrap video', 10000) ||
                                  await waitForElementWithTimeout('#dplayer video', 5000) ||
                                  await waitForElementWithTimeout('.dplayer-video', 3000) ||
                                  await waitForElementWithTimeout('video', 3000);

                    if (video) {
                        console.log('[学习助手] 检测到视频元素');
                        await handleVideo(video, courseData);
                    } else {
                        const pptIframeRetry = detectPPTIframe();
                        if (pptIframeRetry) {
                            console.log('[学习助手] 重试检测到PPT iframe');
                            await handlePPT(courseData);
                        } else {
                            // 非PPT非视频课件(可能是文档、图片等)
                            console.log('[学习助手] 检测到非PPT非视频课件,等待倒计时...');
                            currentTask.value = '非视频课件,等待倒计时...';

                            // 等待倒计时结束(如果有的话)
                            await waitForCountdownEnd();

                            // 等待图标变化确认完成
                            currentTask.value = '等待图标确认...';
                            await waitForCompletionIcon(courseData, 30000);
                        }
                    }
                }
            }

            // 最终检查是否完成
            const finalCompleted = isCourseCompleted(courseData);
            return finalCompleted ? 'success' : 'fail';
        };

        // 初始化队列
        const initQueue = (courses) => {
            // 过滤出未完成的课件
            const uncompletedCourses = courses.filter(c =>
                c.category === '课件' && !c.isCompleted
            );

            courseQueue.value = uncompletedCourses;
            queueIndex.value = 0;
            completedCount.value = 0;
            failCount.value = 0;
            totalProcessed.value = 0;
            shouldStop.value = false;

            console.log('[学习助手] 队列初始化完成,待处理课件:', uncompletedCourses.length);
            return uncompletedCourses.length;
        };

        // 停止队列
        const stopQueue = () => {
            shouldStop.value = true;
            isLearning.value = false;
            currentTask.value = '已停止';
            console.log('[学习助手] 队列已停止');
        };

        // 队列处理主循环
        const processQueue = async () => {
            if (courseQueue.value.length === 0) {
                currentTask.value = '没有待处理的课件';
                return;
            }

            isLearning.value = true;
            shouldStop.value = false;

            let skipCount = 0;  // 连续跳过计数

            while (queueIndex.value < courseQueue.value.length && !shouldStop.value) {
                const courseData = courseQueue.value[queueIndex.value];
                const remaining = courseQueue.value.length - queueIndex.value;

                currentTask.value = `处理中 [${queueIndex.value + 1}/${courseQueue.value.length}]: ${courseData.title}`;
                console.log('[学习助手] ========== 处理课件', queueIndex.value + 1, '/', courseQueue.value.length, '索引:', courseData.domIndex, '==========');

                try {
                    const result = await processSingleCourse(courseData);

                    if (result === 'success') {
                        completedCount.value++;
                        failCount.value = 0;
                        skipCount = 0;
                        totalProcessed.value++;  // 只有成功才计入刷新计数
                        console.log('[学习助手] 课件完成:', courseData.title);
                        courseData.isCompleted = true;
                    } else if (result === 'skip') {
                        completedCount.value++;
                        skipCount++;
                        // 跳过不计入totalProcessed,不触发定期刷新
                        courseData.isCompleted = true;
                        console.log('[学习助手] 跳过已完成课件,连续跳过:', skipCount);
                    } else {
                        failCount.value++;
                        skipCount = 0;
                        totalProcessed.value++;  // 失败也计入刷新计数
                        console.log('[学习助手] 课件处理失败,连续失败次数:', failCount.value);
                    }

                    queueIndex.value++;

                    // 检查是否需要刷新
                    if (failCount.value >= CONFIG.MAX_CONTINUOUS_FAIL) {
                        console.log('[学习助手] 连续失败次数过多,刷新页面重新扫描');
                        currentTask.value = '连续失败过多,3秒后刷新页面...';
                        localStorage.setItem('autoLearningActive', 'true');
                        localStorage.setItem('autoLearningReason', 'continuous_fail');
                        await new Promise(resolve => setTimeout(resolve, 3000));
                        window.location.reload();
                        return;
                    }

                    // 只有真正处理了的课件才触发定期刷新
                    if (totalProcessed.value > 0 && totalProcessed.value % CONFIG.REFRESH_EVERY_N === 0) {
                        console.log('[学习助手] 已处理', totalProcessed.value, '个课件,刷新页面同步状态');
                        currentTask.value = '定期刷新,3秒后刷新页面...';
                        localStorage.setItem('autoLearningActive', 'true');
                        localStorage.setItem('autoLearningReason', 'periodic_refresh');
                        await new Promise(resolve => setTimeout(resolve, 3000));
                        window.location.reload();
                        return;
                    }

                    // 如果不是跳过,课件之间休息一下
                    if (result !== 'skip' && queueIndex.value < courseQueue.value.length && !shouldStop.value) {
                        currentTask.value = '等待2秒后处理下一个...';
                        await new Promise(resolve => setTimeout(resolve, 2000));
                    }

                } catch (error) {
                    console.error('[学习助手] 处理课件出错:', error);
                    failCount.value++;
                    queueIndex.value++;

                    // 检测是否是403错误
                    if (error.message && error.message.includes('403')) {
                        console.log('[学习助手] 检测到403错误,等待5分钟后刷新');
                        currentTask.value = '检测到403,等待5分钟后刷新...';
                        localStorage.setItem('autoLearningActive', 'true');
                        localStorage.setItem('autoLearningReason', '403_wait');
                        await new Promise(resolve => setTimeout(resolve, CONFIG.WAIT_AFTER_403));
                        window.location.reload();
                        return;
                    }
                }
            }

            isLearning.value = false;

            if (shouldStop.value) {
                currentTask.value = '已手动停止';
            } else {
                currentTask.value = `队列处理完成!成功: ${completedCount.value}/${courseQueue.value.length}`;
                console.log('[学习助手] 队列处理完成,成功:', completedCount.value, '/', courseQueue.value.length);

                // 如果还有失败的,可以选择刷新重试
                const hasRemaining = courseQueue.value.some(c => !c.isCompleted);
                if (hasRemaining) {
                    currentTask.value += ' (仍有未完成课件,建议刷新重试)';
                }
            }
        };

        // 兼容旧的startAutoLearning(单个课件)
        const startAutoLearning = async (courseData) => {
            isLearning.value = true;
            const result = await processSingleCourse(courseData);
            isLearning.value = false;
            return result === 'success' || result === 'skip';
        };

        return {
            isLearning,
            currentTask,
            progress,
            courseQueue,
            queueIndex,
            completedCount,
            failCount,
            shouldStop,
            startAutoLearning,
            initQueue,
            processQueue,
            stopQueue,
            isCourseCompleted
        };
    }

    // ===============================
    // AI自动答题组合函数
    // ===============================

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

    function useAutoAnswer() {
        const isAnswering = ref(false);
        const isCompleting = ref(false);
        const autoSubmit = ref(false);
        const autoSave = ref(true);
        const currentStatus = ref('');
        const answeredCount = ref(0);
        const totalQuestions = ref(0);
        const logs = ref([]);

        let answerObserver = null;
        let completeObserver = null;
        let submitRetryCount = 0;

        const log = (message) => {
            const timestamp = new Date().toLocaleTimeString();
            console.log(`[${timestamp}][自动答题] ${message}`);
            logs.value.unshift({ time: timestamp, msg: message });
            if (logs.value.length > 50) logs.value.pop();
        };

        const simulateOptionClick = (optionElement) => {
            const titleElement = optionElement.querySelector('.index, .title');
            if (titleElement) {
                ['mousedown', 'mouseup', 'click'].forEach(eventType => {
                    const event = new MouseEvent(eventType, {
                        view: window,
                        bubbles: true,
                        cancelable: true
                    });
                    titleElement.dispatchEvent(event);
                });
            }
        };

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

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

            const data = await response.json();
            if (data.choices?.[0]?.message?.content) {
                return data.choices[0].message.content.trim();
            }
            throw new Error('API返回数据格式错误');
        };

        const processSingleChoice = async (node) => {
            const questionElement = node.querySelector('.single-select-title');
            if (!questionElement) return;

            const questionText = questionElement.innerText.trim();
            currentStatus.value = `处理单选题: ${questionText.substring(0, 30)}...`;
            log(`处理单选题: ${questionText}`);

            const optionsElements = node.querySelectorAll('.single-option-item');
            let optionsText = '';
            let optionMap = {};

            optionsElements.forEach(option => {
                const indexEl = option.querySelector('.index');
                const titleEl = option.querySelector('.title');
                if (indexEl && titleEl) {
                    const letter = indexEl.innerText.trim();
                    optionsText += `${letter}. ${titleEl.innerText.trim()}\n`;
                    optionMap[letter.toUpperCase()] = option;
                }
            });

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

            try {
                const answer = await getAnswerFromAPI(prompt);
                const match = answer.toUpperCase().trim().match(/[A-D]/);
                if (match && optionMap[match[0]]) {
                    simulateOptionClick(optionMap[match[0]]);
                    node.setAttribute('data-answered', 'true');
                    answeredCount.value++;
                    log(`单选题选择: ${match[0]}`);
                }
            } catch (err) {
                log(`单选题错误: ${err.message}`);
            }
        };

        const processMultipleChoice = async (node) => {
            const questionElement = node.querySelector('.multiple-select-title');
            if (!questionElement) return;

            const questionText = questionElement.innerText.trim();
            currentStatus.value = `处理多选题: ${questionText.substring(0, 30)}...`;
            log(`处理多选题: ${questionText}`);

            const optionsElements = node.querySelectorAll('.multiple-option-item');
            let optionsText = '';
            let optionMap = {};

            optionsElements.forEach(option => {
                const indexEl = option.querySelector('.index');
                const titleEl = option.querySelector('.title');
                if (indexEl && titleEl) {
                    const letter = indexEl.innerText.trim();
                    optionsText += `${letter}. ${titleEl.innerText.trim()}\n`;
                    optionMap[letter.toUpperCase()] = option;
                }
            });

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

            try {
                const answer = await getAnswerFromAPI(prompt);
                const matches = answer.toUpperCase().trim().match(/[A-D]/g);
                if (matches) {
                    const selectedLetters = [...new Set(matches)];
                    selectedLetters.forEach(letter => {
                        if (optionMap[letter]) simulateOptionClick(optionMap[letter]);
                    });
                    node.setAttribute('data-answered', 'true');
                    answeredCount.value++;
                    log(`多选题选择: ${selectedLetters.join(',')}`);
                }
            } catch (err) {
                log(`多选题错误: ${err.message}`);
            }
        };

        const processTrueFalse = async (node) => {
            const questionElement = node.querySelector('.bol-select-title');
            if (!questionElement) return;

            const questionText = questionElement.innerText.trim();
            currentStatus.value = `处理判断题: ${questionText.substring(0, 30)}...`;
            log(`处理判断题: ${questionText}`);

            const optionsElements = node.querySelectorAll('.bol-option-item');
            let optionMap = {};

            optionsElements.forEach(option => {
                const titleEl = option.querySelector('.title');
                if (titleEl) {
                    optionMap[titleEl.innerText.trim().toLowerCase()] = option;
                }
            });

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

            try {
                const answer = await getAnswerFromAPI(prompt);
                const match = answer.trim().match(/^(对|错)$/i);
                if (match && optionMap[match[1].toLowerCase()]) {
                    simulateOptionClick(optionMap[match[1].toLowerCase()]);
                    node.setAttribute('data-answered', 'true');
                    answeredCount.value++;
                    log(`判断题选择: ${match[1]}`);
                }
            } catch (err) {
                log(`判断题错误: ${err.message}`);
            }
        };

        const processEssayQuestion = async (node) => {
            const questionElement = node.querySelector('.essay-select-title');
            if (!questionElement) return;

            const questionText = questionElement.innerText.trim();
            currentStatus.value = `处理论述题: ${questionText.substring(0, 30)}...`;
            log(`处理论述题: ${questionText}`);

            const textareaElement = node.querySelector('.essay-option-item textarea');
            if (!textareaElement) return;

            const prompt = `请根据以下论述题提供一个详细且全面的回答:
问题:${questionText}
回答:`;

            try {
                const answer = await getAnswerFromAPI(prompt);
                textareaElement.focus();
                textareaElement.value = answer;
                textareaElement.dispatchEvent(new Event('input', { bubbles: true }));
                node.setAttribute('data-answered', 'true');
                answeredCount.value++;
                log(`论述题已填充答案`);

                if (autoSave.value) {
                    const saveBtn = node.querySelector('.submit-inner-box');
                    if (saveBtn) saveBtn.click();
                }
            } catch (err) {
                log(`论述题错误: ${err.message}`);
            }
        };

        const handleQuestionNode = async (node) => {
            if (node.getAttribute('data-answered') === 'true') return;

            if (node.querySelector('.single-select-container')) {
                await processSingleChoice(node);
            } else if (node.querySelector('.multiple-select-container')) {
                await processMultipleChoice(node);
            } else if (node.querySelector('.bol-select-container')) {
                await processTrueFalse(node);
            } else if (node.querySelector('.essay-select-container')) {
                await processEssayQuestion(node);
            }

            if (autoSubmit.value) {
                setTimeout(() => checkAndSubmit(), 2000);
            }
        };

        const handleTextTaskNode = async (node) => {
            if (node.getAttribute('data-processed') === 'true') return;

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

            if (!titleElement || !contentElement || !editorElement) return;

            const taskTitle = titleElement.innerText.trim();
            const taskContent = contentElement.innerText.trim();
            currentStatus.value = `处理作业: ${taskTitle.substring(0, 30)}...`;
            log(`处理作业: ${taskTitle}`);

            const prompt = `请根据以下任务内容完成作答,并直接返回答案文本:
任务标题:${taskTitle}
任务内容:${taskContent}
答案:`;

            try {
                const answer = await getAnswerFromAPI(prompt);
                editorElement.focus();
                editorElement.innerHTML = '';
                editorElement.innerText = answer;
                editorElement.dispatchEvent(new Event('input', { bubbles: true }));
                node.setAttribute('data-processed', 'true');
                answeredCount.value++;
                log(`作业已填充答案`);

                if (autoSave.value && saveButton) {
                    saveButton.click();
                }
            } catch (err) {
                log(`作业错误: ${err.message}`);
            }
        };

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

        const submitAnswers = () => {
            const submitButton = document.querySelector('.submit-button, .submit-btn, .confirm-btn');
            if (submitButton && !submitButton.disabled) {
                submitButton.click();
                log('点击提交按钮');

                setTimeout(() => {
                    const confirmBtn = document.querySelector('.ant-modal-content .ant-modal-confirm-btns .ant-btn-primary');
                    if (confirmBtn) {
                        confirmBtn.click();
                        log('点击确认按钮');
                    }
                }, 1000);
            }
        };

        const checkAndSubmit = () => {
            if (hasIncompleteQuestions()) {
                const incompleteNodes = document.querySelectorAll('.question-item:not([data-answered="true"])');
                incompleteNodes.forEach(node => handleQuestionNode(node));
                setTimeout(checkAndSubmit, 3000);
            } else {
                log('所有题目已完成,准备提交');
                submitAnswers();
            }
        };

        const clickStartButton = async () => {
            const startBtn = document.querySelector('.start-btn');
            if (startBtn && startBtn.offsetParent !== null) {
                log(`点击开始作答按钮`);
                startBtn.click();
                await new Promise(r => setTimeout(r, 3000));
                return true;
            }

            const selectors = ['.begin-btn', '.start-answer-btn', '.ant-btn-primary', 'button'];
            const targetTexts = ['开始', '开始答题', '开始作答', '进入答题', '立即答题'];

            for (const selector of selectors) {
                try {
                    const elements = document.querySelectorAll(selector);
                    for (const el of elements) {
                        const text = el.textContent.trim();
                        if (targetTexts.some(t => text.includes(t)) && el.offsetParent !== null) {
                            log(`点击按钮: ${text}`);
                            el.click();
                            await new Promise(r => setTimeout(r, 3000));
                            return true;
                        }
                    }
                } catch (e) {}
            }
            return false;
        };

        const startAnswering = async () => {
            if (isAnswering.value) {
                isAnswering.value = false;
                currentStatus.value = '已停止';
                if (answerObserver) {
                    answerObserver.disconnect();
                    answerObserver = null;
                }
                log('停止自动答题');
                return;
            }

            isAnswering.value = true;
            answeredCount.value = 0;
            currentStatus.value = '扫描题目中...';
            log('开始自动答题');

            let questionNodes = document.querySelectorAll('.question-item:not([data-answered="true"])');

            if (questionNodes.length === 0) {
                log('未找到题目,尝试点击开始按钮...');
                currentStatus.value = '尝试进入答题页面...';
                const clicked = await clickStartButton();
                if (clicked) {
                    await new Promise(r => setTimeout(r, 2000));
                    questionNodes = document.querySelectorAll('.question-item:not([data-answered="true"])');
                }
            }

            totalQuestions.value = questionNodes.length;
            log(`找到 ${questionNodes.length} 个未回答的题目`);

            if (questionNodes.length === 0) {
                log('未找到题目,请确认已进入答题页面');
                currentStatus.value = '未找到题目';
            }

            questionNodes.forEach(node => handleQuestionNode(node));

            answerObserver = new MutationObserver((mutations) => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1) {
                            if (node.classList?.contains('question-item')) {
                                handleQuestionNode(node);
                            }
                            node.querySelectorAll?.('.question-item').forEach(child => {
                                handleQuestionNode(child);
                            });
                        }
                    });
                });
            });
            answerObserver.observe(document.body, { childList: true, subtree: true });
        };

        const startCompleting = async () => {
            if (isCompleting.value) {
                isCompleting.value = false;
                currentStatus.value = '已停止';
                if (completeObserver) {
                    completeObserver.disconnect();
                    completeObserver = null;
                }
                log('停止自动完成作业');
                return;
            }

            isCompleting.value = true;
            answeredCount.value = 0;
            currentStatus.value = '扫描作业中...';
            log('开始自动完成作业');

            let taskNodes = document.querySelectorAll('.question-container:not([data-processed="true"])');

            if (taskNodes.length === 0) {
                log('未找到作业容器,尝试点击开始按钮...');
                currentStatus.value = '尝试进入答题页面...';
                const clicked = await clickStartButton();
                if (clicked) {
                    await new Promise(r => setTimeout(r, 2000));
                    taskNodes = document.querySelectorAll('.question-container:not([data-processed="true"])');
                }
            }

            totalQuestions.value = taskNodes.length;
            log(`找到 ${taskNodes.length} 个未处理的作业`);

            if (taskNodes.length === 0) {
                log('未找到作业,请确认已进入作业页面');
                currentStatus.value = '未找到作业';
            }

            taskNodes.forEach(node => handleTextTaskNode(node));

            completeObserver = new MutationObserver((mutations) => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1) {
                            if (node.classList?.contains('question-container')) {
                                handleTextTaskNode(node);
                            }
                            node.querySelectorAll?.('.question-container').forEach(child => {
                                handleTextTaskNode(child);
                            });
                        }
                    });
                });
            });
            completeObserver.observe(document.body, { childList: true, subtree: true });
        };

        const toggleAutoSubmit = () => {
            autoSubmit.value = !autoSubmit.value;
            log(`自动提交: ${autoSubmit.value ? '开启' : '关闭'}`);
            if (autoSubmit.value) checkAndSubmit();
        };

        const toggleAutoSave = () => {
            autoSave.value = !autoSave.value;
            log(`自动保存: ${autoSave.value ? '开启' : '关闭'}`);
        };

        return {
            isAnswering,
            isCompleting,
            autoSubmit,
            autoSave,
            currentStatus,
            answeredCount,
            totalQuestions,
            logs,
            startAnswering,
            startCompleting,
            toggleAutoSubmit,
            toggleAutoSave
        };
    }

    // 设置管理组合函数
    function useSettings() {
        // 默认三倍速,如果没有存储值则立即写入
        if (!localStorage.getItem('videoPlaybackSpeed')) {
            localStorage.setItem('videoPlaybackSpeed', '3');
        }
        const videoSpeed = ref(parseFloat(localStorage.getItem('videoPlaybackSpeed')) || 3);

        // 保存视频倍速并应用到当前播放的视频
        const saveVideoSpeed = () => {
            localStorage.setItem('videoPlaybackSpeed', videoSpeed.value.toString());

            // 立即应用到当前播放的视频
            const videos = document.querySelectorAll('video');
            videos.forEach(video => {
                if (video && !video.paused) {
                    video.playbackRate = videoSpeed.value;
                }
            });
        };

        return {
            videoSpeed,
            saveVideoSpeed
        };
    }

    // 讨论回复组合函数
    function useDiscussionReply() {
        const isReplying = ref(false);
        const replyProgress = ref({ current: 0, total: 0 });

        // 获取已回复的讨论列表
        const getRepliedDiscussions = () => {
            try {
                const data = localStorage.getItem('repliedDiscussions');
                return data ? JSON.parse(data) : [];
            } catch {
                return [];
            }
        };

        // 保存已回复的讨论
        const saveRepliedDiscussion = (title) => {
            const replied = getRepliedDiscussions();
            if (!replied.includes(title)) {
                replied.push(title);
                localStorage.setItem('repliedDiscussions', JSON.stringify(replied));
            }
        };

        // 检查讨论是否已回复
        const isDiscussionReplied = (title) => {
            return getRepliedDiscussions().includes(title);
        };

        // 初始化讨论的回复状态(扫描时调用)
        const initReplyStatus = (courseData) => {
            if (isDiscussionReplied(courseData.title)) {
                courseData.replyStatus = '已回复';
            }
        };

        // 重新查找元素(处理DOM更新后元素失效的情况)
        const refreshElement = (courseData) => {
            // 检查元素是否还在DOM中
            if (document.body.contains(courseData.element)) {
                return courseData.element;
            }

            // 尝试通过标题重新查找
            const title = courseData.title;
            if (title) {
                const allItems = document.querySelectorAll('.third-level-inner-box');
                for (const item of allItems) {
                    const titleEl = item.querySelector('p.title, p.title-big');
                    if (titleEl && titleEl.textContent.trim() === title) {
                        courseData.element = item;
                        return item;
                    }
                }
            }

            return null;
        };

        // 跳转到课件
        const jumpToItem = async (courseData) => {
            try {
                // 先刷新元素引用
                const targetElement = refreshElement(courseData);
                if (!targetElement) {
                    console.error('跳转失败:找不到目标元素', courseData.title);
                    return false;
                }

                await expandAllParentsAsync(targetElement);
                const clickable = targetElement.querySelector('a') ||
                      targetElement.querySelector('p.title') ||
                      targetElement;

                if (clickable) {
                    clickable.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    await new Promise(resolve => setTimeout(resolve, 500));
                    simulateClick(clickable);
                    return true;
                }
            } catch (error) {
                console.error('跳转失败:', error);
            }
            return false;
        };

        // 自动回复单个讨论
        const performAutoReply = async (courseData) => {
            try {
                await jumpToItem(courseData);
                await new Promise(resolve => setTimeout(resolve, 1000));

                const discussionArea = await waitForElement('.course-courseQaDiscussion-qa', 5000);
                if (!discussionArea) return false;

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

                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 }));
                    await new Promise(resolve => setTimeout(resolve, 500));
                    submitButton.click();
                    courseData.replyStatus = '已回复';
                    // 保存到localStorage
                    saveRepliedDiscussion(courseData.title);
                    return true;
                }

                return false;
            } catch (error) {
                console.error('自动回复失败:', error);
                return false;
            }
        };

        // 批量自动回复
        const batchAutoReply = async (discussionItems) => {
            isReplying.value = true;
            replyProgress.value = { current: 0, total: discussionItems.length };

            for (let i = 0; i < discussionItems.length; i++) {
                const item = discussionItems[i];
                replyProgress.value.current = i + 1;

                await performAutoReply(item);
                await new Promise(resolve => setTimeout(resolve, 1000));
            }

            isReplying.value = false;
        };

        return {
            isReplying,
            replyProgress,
            performAutoReply,
            jumpToItem,
            batchAutoReply,
            initReplyStatus
        };
    }

    // 测验/作业信息获取组合函数
    function useTestAssignmentInfo() {
        const isCollecting = ref(false);
        const collectProgress = ref({ current: 0, total: 0 });

        // 重新查找元素(处理DOM更新后元素失效的情况)
        const refreshElement = (courseData) => {
            if (document.body.contains(courseData.element)) {
                return courseData.element;
            }

            const title = courseData.title;
            if (title) {
                const allItems = document.querySelectorAll('.third-level-inner-box');
                for (const item of allItems) {
                    const titleEl = item.querySelector('p.title, p.title-big');
                    if (titleEl && titleEl.textContent.trim() === title) {
                        courseData.element = item;
                        return item;
                    }
                }
            }

            return null;
        };

        // 跳转到课件
        const jumpToItem = async (courseData) => {
            try {
                const targetElement = refreshElement(courseData);
                if (!targetElement) {
                    console.error('跳转失败:找不到目标元素', courseData.title);
                    return false;
                }

                await expandAllParentsAsync(targetElement);
                const clickable = targetElement.querySelector('a') ||
                      targetElement.querySelector('p.title') ||
                      targetElement;

                if (clickable) {
                    clickable.scrollIntoView({ behavior: 'smooth', block: 'center' });
                    await new Promise(resolve => setTimeout(resolve, 500));
                    simulateClick(clickable);
                    return true;
                }
            } catch (error) {
                console.error('跳转失败:', error);
            }
            return false;
        };

        // 获取作答次数信息
        const getAttemptInfo = async () => {
            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);
                        resolve('获取失败');
                    }
                }, 100);
            });
        };

        // 获取时间信息
        const getTimeInfo = async () => {
            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);
                        resolve('获取失败');
                    }
                }, 100);
            });
        };

        // 收集测验信息
        const collectTestInfo = async (testItems) => {
            isCollecting.value = true;
            collectProgress.value = { current: 0, total: testItems.length };

            for (let i = 0; i < testItems.length; i++) {
                const item = testItems[i];
                collectProgress.value.current = i + 1;

                await jumpToItem(item);
                await new Promise(resolve => setTimeout(resolve, 1000));

                const attemptInfo = await getAttemptInfo();
                const timeInfo = await getTimeInfo();

                item.attemptInfo = attemptInfo;
                item.timeInfo = timeInfo;

                await new Promise(resolve => setTimeout(resolve, 500));
            }

            isCollecting.value = false;
        };

        // 收集作业信息
        const collectAssignmentInfo = async (assignmentItems) => {
            isCollecting.value = true;
            collectProgress.value = { current: 0, total: assignmentItems.length };

            for (let i = 0; i < assignmentItems.length; i++) {
                const item = assignmentItems[i];
                collectProgress.value.current = i + 1;

                await jumpToItem(item);
                await new Promise(resolve => setTimeout(resolve, 1000));

                const attemptInfo = await getAttemptInfo();
                const timeInfo = await getTimeInfo();

                item.attemptInfo = attemptInfo;
                item.timeInfo = timeInfo;

                await new Promise(resolve => setTimeout(resolve, 500));
            }

            isCollecting.value = false;
        };

        return {
            isCollecting,
            collectProgress,
            collectTestInfo,
            collectAssignmentInfo,
            jumpToItem
        };
    }

    // ===============================
    // Vue 3 主应用(返回app实例的函数)
    // ===============================

    function createVueApp() {
        return createApp({
        setup() {
            // 组合函数
            const courseScanner = useCourseScanner();
            const autoLearning = useAutoLearning();
            const settings = useSettings();
            const discussionReply = useDiscussionReply();
            const testAssignmentInfo = useTestAssignmentInfo();
            const autoAnswer = useAutoAnswer();

            // 响应式数据
            const isVisible = ref(true);
            const activeTab = ref('auto');
            const expandedCategories = ref({});
            const panelRef = ref(null);
            const panelPosition = ref({ top: '10%', right: '20px', left: 'auto' });

            // 拖拽功能
            const initDrag = () => {
                const panel = document.getElementById('learning-assistant-panel');
                if (!panel) return;

                const header = panel.querySelector('.panel-drag-header');
                if (!header) return;

                let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;

                header.onmousedown = (e) => {
                    e.preventDefault();
                    pos3 = e.clientX;
                    pos4 = e.clientY;
                    document.onmouseup = closeDrag;
                    document.onmousemove = elementDrag;
                };

                const elementDrag = (e) => {
                    e.preventDefault();
                    pos1 = pos3 - e.clientX;
                    pos2 = pos4 - e.clientY;
                    pos3 = e.clientX;
                    pos4 = e.clientY;

                    let newTop = panel.offsetTop - pos2;
                    let newLeft = panel.offsetLeft - pos1;

                    const windowWidth = window.innerWidth;
                    const windowHeight = window.innerHeight;
                    const elemWidth = panel.offsetWidth;
                    const elemHeight = panel.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;

                    panel.style.top = newTop + 'px';
                    panel.style.left = newLeft + 'px';
                    panel.style.right = 'auto';
                };

                const closeDrag = () => {
                    document.onmouseup = null;
                    document.onmousemove = null;
                };
            };

            // 计算属性
            const discussionItems = computed(() => {
                return courseScanner.allCourses.value.filter(course => course.category === '讨论');
            });

            const testItems = computed(() => {
                return courseScanner.allCourses.value.filter(course => course.category === '测验');
            });

            const assignmentItems = computed(() => {
                return courseScanner.allCourses.value.filter(course => course.category === '作业');
            });

            const coursewareItems = computed(() => {
                return courseScanner.allCourses.value.filter(course => course.category === '课件');
            });

            // 按类别分组的课件
            const categorizedCourses = computed(() => {
                const categories = {};
                courseScanner.allCourses.value.forEach(course => {
                    if (!categories[course.category]) {
                        categories[course.category] = {
                            items: [],
                            completed: 0,
                            halfCompleted: 0,
                            total: 0
                        };
                    }
                    categories[course.category].items.push(course);
                    categories[course.category].total++;
                    if (course.status === '已完成') {
                        categories[course.category].completed++;
                    } else if (course.status === '半完成') {
                        categories[course.category].halfCompleted++;
                    }
                });
                return categories;
            });

            // 主要方法
            const toggleVisibility = () => {
                isVisible.value = !isVisible.value;
            };

            const toggleCategory = (category) => {
                expandedCategories.value[category] = !expandedCategories.value[category];
            };

            // 跳转到课件
            const jumpToCourse = async (courseData) => {
                await discussionReply.jumpToItem(courseData);
            };

            // 智能自动刷课(队列模式)
            const startSmartLearning = async () => {
                localStorage.setItem('autoLearningActive', 'true');
                await courseScanner.scanAllCourses();

                // 检查是否正常加载了课件
                const totalCourses = courseScanner.allCourses.value.length;
                if (totalCourses === 0) {
                    console.log('[学习助手] 未检测到课件,可能页面未正常加载,5秒后刷新重试...');
                    autoLearning.currentTask.value = '页面异常,5秒后刷新重试...';
                    setTimeout(() => {
                        window.location.reload();
                    }, 5000);
                    return;
                }

                // 初始化队列
                const queueSize = autoLearning.initQueue(courseScanner.allCourses.value);

                if (queueSize === 0) {
                    // 所有课件都已完成
                    const coursewareCount = courseScanner.allCourses.value.filter(c => c.category === '课件').length;
                    if (coursewareCount === 0) {
                        console.log('[学习助手] 未检测到课件分类,可能页面异常,5秒后刷新重试...');
                        autoLearning.currentTask.value = '未检测到课件,5秒后刷新重试...';
                        setTimeout(() => {
                            window.location.reload();
                        }, 5000);
                        return;
                    }

                    localStorage.removeItem('autoLearningActive');
                    localStorage.removeItem('autoLearningReason');
                    autoLearning.currentTask.value = '所有课件已完成!';
                    alert('恭喜!所有课件都已完成!');
                    return;
                }

                console.log('[学习助手] 开始队列处理,待处理课件:', queueSize);

                // 开始处理队列
                await autoLearning.processQueue();

                // 队列处理完成后,检查是否全部完成
                const remainingCount = autoLearning.courseQueue.value.filter(c => !c.isCompleted).length;
                if (remainingCount === 0) {
                    localStorage.removeItem('autoLearningActive');
                    localStorage.removeItem('autoLearningReason');
                    console.log('[学习助手] 所有课件处理完成!');
                }
            };

            // 停止自动刷课
            const stopAutoLearning = () => {
                localStorage.removeItem('autoLearningActive');
                localStorage.removeItem('autoLearningReason');
                autoLearning.stopQueue();
            };

            // 检查是否需要自动继续
            const checkAutoResume = async () => {
                const isActive = localStorage.getItem('autoLearningActive');
                if (isActive === 'true') {
                    const reason = localStorage.getItem('autoLearningReason') || 'unknown';
                    console.log('[学习助手] 检测到自动刷课状态,原因:', reason, ',3秒后继续...');
                    autoLearning.currentTask.value = '3秒后自动继续...';
                    setTimeout(() => {
                        startSmartLearning();
                    }, 3000);
                }
            };

            // 初始化
            onMounted(async () => {
                await courseScanner.scanAllCourses();
                checkAutoResume();
                // 初始化拖拽功能
                setTimeout(() => initDrag(), 100);
            });

            // 获取测验信息
            const collectTestInfoBtn = async () => {
                await testAssignmentInfo.collectTestInfo(testItems.value);
            };

            // 获取作业信息
            const collectAssignmentInfoBtn = async () => {
                await testAssignmentInfo.collectAssignmentInfo(assignmentItems.value);
            };

            return {
                // 数据
                isVisible,
                activeTab,
                expandedCategories,

                // 组合函数
                courseScanner,
                autoLearning,
                settings,
                discussionReply,
                testAssignmentInfo,
                autoAnswer,

                // 计算属性
                discussionItems,
                testItems,
                assignmentItems,
                coursewareItems,
                categorizedCourses,

                // 方法
                toggleVisibility,
                toggleCategory,
                jumpToCourse,
                startSmartLearning,
                stopAutoLearning,
                collectTestInfoBtn,
                collectAssignmentInfoBtn
            };
        },

        template: `
            <!-- 控制按钮 -->
            <div v-if="!isVisible" @click="toggleVisibility"
                 style="position: fixed; bottom: 20px; left: 20px; z-index: 10001;
                        padding: 12px 20px; background: linear-gradient(135deg, #7EC8E3 0%, #5BA4C9 100%);
                        color: #FFFEF7; border-radius: 20px; cursor: pointer; box-shadow: 0 4px 15px rgba(126,200,227,0.4);
                        font-weight: 600; transition: all 0.3s ease; border: 2px solid rgba(255,255,255,0.3);">
                ☁️ 学习助手
            </div>

            <!-- 主面板 -->
            <div v-if="isVisible" id="learning-assistant-panel" style="position: fixed; top: 20px; right: 20px; width: 380px; max-height: 90vh; overflow-y: auto; z-index: 10000;
                                       background: #FFFEF7; border-radius: 20px; box-shadow: 0 8px 32px rgba(139,115,85,0.15);
                                       overflow: hidden; font-family: 'Hiragino Sans', 'Microsoft YaHei', sans-serif; border: 2px solid rgba(139,115,85,0.1);">

                <!-- 头部(可拖拽) -->
                <div class="panel-drag-header" style="background: linear-gradient(135deg, #7EC8E3 0%, #A8D8EA 100%); padding: 18px 20px; color: #FFFEF7; cursor: move; position: relative; overflow: hidden;">
                    <!-- 装饰云朵 -->
                    <div style="position: absolute; top: -10px; right: 20px; font-size: 40px; opacity: 0.3;">☁️</div>
                    <div style="position: absolute; bottom: -5px; left: 30px; font-size: 25px; opacity: 0.2;">☁️</div>
                    <div style="display: flex; justify-content: space-between; align-items: center; position: relative; z-index: 1;">
                        <div>
                            <h3 style="margin: 0; font-size: 18px; font-weight: 600; text-shadow: 0 1px 2px rgba(0,0,0,0.1);">🌿 CQOOC智慧学习助手</h3>
                            <p style="margin: 4px 0 0; opacity: 0.9; font-size: 12px;">~ 这个班是上不了一点😡 ~</p>
                        </div>
                        <button @click="toggleVisibility"
                                style="background: rgba(255,255,255,0.25); border: none; color: white;
                                       width: 28px; height: 28px; border-radius: 14px; cursor: pointer; font-size: 14px;
                                       transition: all 0.2s ease;">×</button>
                    </div>
                </div>

                <!-- 统计卡片 -->
                <div style="padding: 15px 20px; background: linear-gradient(180deg, #F0F9FF 0%, #FFFEF7 100%);">
                    <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px;">
                        <div style="text-align: center; padding: 12px; background: #FFFEF7; border-radius: 12px; box-shadow: 0 2px 8px rgba(139,115,85,0.08); border: 1px solid rgba(126,200,227,0.2);">
                            <div style="font-size: 22px; font-weight: bold; color: #7EC8E3;">{{courseScanner.statistics.value.total}}</div>
                            <div style="font-size: 11px; color: #8B7355; margin-top: 2px;">总课件</div>
                        </div>
                        <div style="text-align: center; padding: 12px; background: #FFFEF7; border-radius: 12px; box-shadow: 0 2px 8px rgba(139,115,85,0.08); border: 1px solid rgba(144,183,125,0.2);">
                            <div style="font-size: 22px; font-weight: bold; color: #90B77D;">{{courseScanner.statistics.value.completed}}</div>
                            <div style="font-size: 11px; color: #8B7355; margin-top: 2px;">已完成</div>
                        </div>
                        <div style="text-align: center; padding: 12px; background: #FFFEF7; border-radius: 12px; box-shadow: 0 2px 8px rgba(139,115,85,0.08); border: 1px solid rgba(255,171,118,0.2);">
                            <div style="font-size: 22px; font-weight: bold; color: #FFAB76;">{{courseScanner.statistics.value.remaining}}</div>
                            <div style="font-size: 11px; color: #8B7355; margin-top: 2px;">待学习</div>
                        </div>
                    </div>

                    <!-- 公告区域 -->
                    <div style="margin-top: 12px; padding: 10px 14px; background: linear-gradient(135deg, #FFF8E7 0%, #FFEFDB 100%); border-radius: 10px; border: 1px dashed #FFAB76;">
                        <div style="display: flex; align-items: center; gap: 8px;">
                            <span style="font-size: 16px;">🍃</span>
                            <span style="font-size: 12px; color: #8B7355; line-height: 1.5;">
                                1.反馈群:1006332809 <br>
                                2.需要保证窗口可见,不能切到后台  <br>
                                3.讨论回复功能是直接复制讨论区第一条来回复的 <br>
                                4.如果有问题的加群反馈吧,应该有没考虑到的情况 <br>
                                5.默认三倍速<br>
                                6.答题需要你先进入到具体的答题页面然后开启自动答题才会搜答案,不人性化将就下
                            </span>
                        </div>
                    </div>
                </div>

                <!-- 主功能区 -->
                <div style="padding: 0 20px 20px; background: #FFFEF7;">

                    <!-- 智能自动刷课按钮 -->
                    <button v-if="!autoLearning.isLearning.value" @click="startSmartLearning" :disabled="courseScanner.isScanning.value"
                            style="width: 100%; padding: 14px; margin-bottom: 12px; background: linear-gradient(135deg, #90B77D 0%, #7BA86E 100%);
                                   color: #FFFEF7; border: none; border-radius: 12px; font-size: 15px; font-weight: 600;
                                   cursor: pointer; transition: all 0.3s ease; box-shadow: 0 4px 12px rgba(144,183,125,0.3);
                                   border: 2px solid rgba(255,255,255,0.2);">
                        <span v-if="courseScanner.isScanning.value">🔍 扫描课件中...</span>
                        <span v-else>🌸 开始智能学习</span>
                    </button>

                    <!-- 正在学习时显示状态和停止按钮 -->
                    <div v-else style="margin-bottom: 12px;">
                        <div style="padding: 12px 14px; background: linear-gradient(135deg, #E8F5E9 0%, #F1F8E9 100%); border-radius: 10px; margin-bottom: 10px; border: 1px solid rgba(144,183,125,0.3);">
                            <div style="font-weight: 600; color: #6B8E5F; margin-bottom: 4px; font-size: 13px;">{{autoLearning.currentTask.value}}</div>
                            <div style="display: flex; justify-content: space-between; font-size: 12px; color: #90B77D;">
                                <span>进度: {{autoLearning.progress.value}}%</span>
                                <span v-if="autoLearning.courseQueue.value.length > 0">
                                    队列: {{autoLearning.queueIndex.value + 1}}/{{autoLearning.courseQueue.value.length}}
                                </span>
                            </div>
                            <div v-if="autoLearning.failCount.value > 0" style="font-size: 11px; color: #FFAB76; margin-top: 4px;">
                                ⚠️ 连续失败: {{autoLearning.failCount.value}}次
                            </div>
                        </div>
                        <button @click="stopAutoLearning"
                                style="width: 100%; padding: 10px; background: linear-gradient(135deg, #E57373 0%, #D32F2F 100%); color: #FFFEF7; border: none; border-radius: 8px; font-size: 13px; cursor: pointer;">
                            🛑 停止学习
                        </button>
                    </div>

                    <!-- 进度条 -->
                    <div v-if="autoLearning.isLearning.value" style="margin-bottom: 16px;">
                        <div style="background: #E8F5E9; border-radius: 10px; overflow: hidden; height: 6px;">
                            <div style="background: linear-gradient(90deg, #90B77D, #A8D5A2); height: 100%; transition: width 0.3s ease;"
                                 :style="{width: autoLearning.progress.value + '%'}"></div>
                        </div>
                    </div>

                    <!-- 标签页 -->
                    <div style="display: flex; margin-bottom: 12px; background: #F5F0E8; border-radius: 10px; padding: 4px;">
                        <button @click="activeTab = 'auto'"
                                :style="{flex: 1, padding: '8px', border: 'none', borderRadius: '8px', cursor: 'pointer',
                                        background: activeTab === 'auto' ? '#FFFEF7' : 'transparent',
                                        color: activeTab === 'auto' ? '#8B7355' : '#A99880', fontWeight: '500', fontSize: '12px',
                                        boxShadow: activeTab === 'auto' ? '0 2px 4px rgba(139,115,85,0.1)' : 'none'}">
                            功能
                        </button>
                        <button @click="activeTab = 'answer'"
                                :style="{flex: 1, padding: '8px', border: 'none', borderRadius: '8px', cursor: 'pointer',
                                        background: activeTab === 'answer' ? '#FFFEF7' : 'transparent',
                                        color: activeTab === 'answer' ? '#8B7355' : '#A99880', fontWeight: '500', fontSize: '12px',
                                        boxShadow: activeTab === 'answer' ? '0 2px 4px rgba(139,115,85,0.1)' : 'none'}">
                            答题
                        </button>
                        <button @click="activeTab = 'list'"
                                :style="{flex: 1, padding: '8px', border: 'none', borderRadius: '8px', cursor: 'pointer',
                                        background: activeTab === 'list' ? '#FFFEF7' : 'transparent',
                                        color: activeTab === 'list' ? '#8B7355' : '#A99880', fontWeight: '500', fontSize: '12px',
                                        boxShadow: activeTab === 'list' ? '0 2px 4px rgba(139,115,85,0.1)' : 'none'}">
                            列表
                        </button>
                        <button @click="activeTab = 'settings'"
                                :style="{flex: 1, padding: '8px', border: 'none', borderRadius: '8px', cursor: 'pointer',
                                        background: activeTab === 'settings' ? '#FFFEF7' : 'transparent',
                                        color: activeTab === 'settings' ? '#8B7355' : '#A99880', fontWeight: '500', fontSize: '12px',
                                        boxShadow: activeTab === 'settings' ? '0 2px 4px rgba(139,115,85,0.1)' : 'none'}">
                            设置
                        </button>
                    </div>

                    <!-- 自动功能标签页 -->
                    <div v-show="activeTab === 'auto'" style="max-height: 350px; overflow-y: auto;">

                        <!-- 讨论自动回复 -->
                        <div v-if="discussionItems.length > 0" style="margin-bottom: 12px; padding: 14px; background: linear-gradient(135deg, #FFF8E7 0%, #FFEFDB 100%); border-radius: 12px; border: 1px solid rgba(255,171,118,0.3);">
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                                <span style="font-weight: 600; color: #8B7355; font-size: 13px;">💬 讨论区回复</span>
                                <span style="font-size: 11px; color: #FFAB76; background: rgba(255,171,118,0.2); padding: 2px 8px; border-radius: 10px;">{{discussionItems.length}}个</span>
                            </div>
                            <button @click="discussionReply.batchAutoReply(discussionItems)" :disabled="discussionReply.isReplying.value"
                                    style="width: 100%; padding: 8px; background: linear-gradient(135deg, #FFAB76 0%, #FF9A5C 100%); color: #FFFEF7; border: none; border-radius: 8px; font-size: 13px; cursor: pointer;">
                                <span v-if="discussionReply.isReplying.value">
                                    回复中... ({{discussionReply.replyProgress.value.current}}/{{discussionReply.replyProgress.value.total}})
                                </span>
                                <span v-else>✨ 一键回复</span>
                            </button>
                        </div>

                        <!-- 测验信息 -->
                        <div v-if="testItems.length > 0" style="margin-bottom: 12px; padding: 14px; background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 100%); border-radius: 12px; border: 1px solid rgba(126,200,227,0.3);">
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                                <div style="display: flex; align-items: center; gap: 8px;">
                                    <span style="font-weight: 600; color: #5BA4C9; font-size: 13px;">📝 测验信息</span>
                                    <span style="font-size: 11px; color: #7EC8E3; background: rgba(126,200,227,0.2); padding: 2px 8px; border-radius: 10px;">{{testItems.length}}个</span>
                                </div>
                                <button @click="autoAnswer.startAnswering()"
                                        :style="{padding: '4px 10px', fontSize: '11px', border: 'none', borderRadius: '6px', cursor: 'pointer',
                                                background: autoAnswer.isAnswering ? '#E57373' : 'linear-gradient(135deg, #6200EE 0%, #5000D0 100%)', color: '#FFFEF7'}">
                                    {{ autoAnswer.isAnswering ? '停止' : '一键完成' }}
                                </button>
                            </div>
                            <button @click="collectTestInfoBtn" :disabled="testAssignmentInfo.isCollecting.value"
                                    style="width: 100%; padding: 8px; background: linear-gradient(135deg, #7EC8E3 0%, #5BA4C9 100%); color: #FFFEF7; border: none; border-radius: 8px; font-size: 13px; cursor: pointer; margin-bottom: 8px;">
                                <span v-if="testAssignmentInfo.isCollecting.value">
                                    获取中... ({{testAssignmentInfo.collectProgress.value.current}}/{{testAssignmentInfo.collectProgress.value.total}})
                                </span>
                                <span v-else>🔍 获取作答信息</span>
                            </button>
                            <div v-for="item in testItems" :key="item.title" style="font-size: 11px; padding: 6px 0; border-bottom: 1px solid rgba(126,200,227,0.2);">
                                <div style="display: flex; justify-content: space-between; align-items: center;">
                                    <span style="color: #5BA4C9; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{item.title}}</span>
                                    <button @click="jumpToCourse(item)" style="padding: 2px 8px; background: #7EC8E3; color: #FFFEF7; border: none; border-radius: 4px; font-size: 10px; cursor: pointer;">跳转</button>
                                </div>
                                <div v-if="item.attemptInfo" style="color: #8B7355; margin-top: 2px;">📊 {{item.attemptInfo}}</div>
                                <div v-if="item.timeInfo" style="color: #90B77D; margin-top: 2px;">⏰ {{item.timeInfo}}</div>
                            </div>
                        </div>

                        <!-- 作业信息 -->
                        <div v-if="assignmentItems.length > 0" style="margin-bottom: 12px; padding: 14px; background: linear-gradient(135deg, #F3E8FF 0%, #E9D5FF 100%); border-radius: 12px; border: 1px solid rgba(167,139,250,0.3);">
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
                                <div style="display: flex; align-items: center; gap: 8px;">
                                    <span style="font-weight: 600; color: #7C3AED; font-size: 13px;">📋 作业信息</span>
                                    <span style="font-size: 11px; color: #A78BFA; background: rgba(167,139,250,0.2); padding: 2px 8px; border-radius: 10px;">{{assignmentItems.length}}个</span>
                                </div>
                                <button @click="autoAnswer.startCompleting()"
                                        :style="{padding: '4px 10px', fontSize: '11px', border: 'none', borderRadius: '6px', cursor: 'pointer',
                                                background: autoAnswer.isCompleting ? '#E57373' : 'linear-gradient(135deg, #03A9F4 0%, #0288D1 100%)', color: '#FFFEF7'}">
                                    {{ autoAnswer.isCompleting ? '停止' : '一键完成' }}
                                </button>
                            </div>
                            <button @click="collectAssignmentInfoBtn" :disabled="testAssignmentInfo.isCollecting.value"
                                    style="width: 100%; padding: 8px; background: linear-gradient(135deg, #A78BFA 0%, #8B5CF6 100%); color: #FFFEF7; border: none; border-radius: 8px; font-size: 13px; cursor: pointer; margin-bottom: 8px;">
                                <span v-if="testAssignmentInfo.isCollecting.value">
                                    获取中... ({{testAssignmentInfo.collectProgress.value.current}}/{{testAssignmentInfo.collectProgress.value.total}})
                                </span>
                                <span v-else>🔍 获取作业信息</span>
                            </button>
                            <div v-for="item in assignmentItems" :key="item.title" style="font-size: 11px; padding: 6px 0; border-bottom: 1px solid rgba(167,139,250,0.2);">
                                <div style="display: flex; justify-content: space-between; align-items: center;">
                                    <span style="color: #7C3AED; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{item.title}}</span>
                                    <button @click="jumpToCourse(item)" style="padding: 2px 8px; background: #A78BFA; color: #FFFEF7; border: none; border-radius: 4px; font-size: 10px; cursor: pointer;">跳转</button>
                                </div>
                                <div v-if="item.attemptInfo" style="color: #8B7355; margin-top: 2px;">📊 {{item.attemptInfo}}</div>
                                <div v-if="item.timeInfo" style="color: #90B77D; margin-top: 2px;">⏰ {{item.timeInfo}}</div>
                            </div>
                        </div>

                    </div>

                    <!-- 答题标签页 -->
                    <div v-show="activeTab === 'answer'" style="max-height: 350px; overflow-y: auto;">

                        <!-- 说明 -->
                        <div style="margin-bottom: 12px; padding: 10px 12px; background: linear-gradient(135deg, #FFF8E7 0%, #FFEFDB 100%); border-radius: 10px; border: 1px dashed #FFAB76;">
                            <div style="font-size: 11px; color: #8B7355; line-height: 1.6;">
                                1. 先进入到”作业考试这个这个板块“支持单选、多选、判断和论述题<br>
                                2. 图片题目无法识别,仅支持纯文本<br>
                                3. 进入作业/测验页面后点击对应按钮<br>
                                4. 使用免费AI模型,准确率有限<br>
                                5. 作业部分不会的你多点几下,我以后有时间了再优化
                            </div>
                        </div>

                        <!-- 测验/考试区域 -->
                        <div style="margin-bottom: 12px; padding: 14px; background: linear-gradient(135deg, #E8F0FE 0%, #D4E4FC 100%); border-radius: 12px; border: 1px solid rgba(98,0,238,0.2);">
                            <div style="font-weight: 600; color: #6200EE; margin-bottom: 10px; font-size: 13px;">测验/考试</div>

                            <button @click="autoAnswer.startAnswering()"
                                    :style="{width: '100%', padding: '10px', marginBottom: '8px', border: 'none', borderRadius: '8px', cursor: 'pointer', fontSize: '13px', fontWeight: '500',
                                            background: autoAnswer.isAnswering ? 'linear-gradient(135deg, #9575CD 0%, #7E57C2 100%)' : 'linear-gradient(135deg, #6200EE 0%, #5000D0 100%)',
                                            color: '#FFFEF7'}">
                                {{ autoAnswer.isAnswering ? '开始自动答题' : '停止自动答题' }}
                            </button>

                            <button @click="autoAnswer.toggleAutoSubmit()"
                                    :style="{width: '100%', padding: '10px', border: 'none', borderRadius: '8px', cursor: 'pointer', fontSize: '13px', fontWeight: '500',
                                            background: autoAnswer.autoSubmit ? 'linear-gradient(135deg, #009688 0%, #00796B 100%)' : 'linear-gradient(135deg, #03DAC6 0%, #00BFA5 100%)',
                                            color: autoAnswer.autoSubmit ? '#FFFEF7' : '#004D40'}">
                                {{ autoAnswer.autoSubmit ? '关闭自动提交' : '开启自动提交' }}
                            </button>
                        </div>

                        <!-- 作业区域 -->
                        <div style="margin-bottom: 12px; padding: 14px; background: linear-gradient(135deg, #E3F2FD 0%, #BBDEFB 100%); border-radius: 12px; border: 1px solid rgba(3,169,244,0.2);">
                            <div style="font-weight: 600; color: #0288D1; margin-bottom: 10px; font-size: 13px;">作业</div>

                            <button @click="autoAnswer.startCompleting()"
                                    :style="{width: '100%', padding: '10px', marginBottom: '8px', border: 'none', borderRadius: '8px', cursor: 'pointer', fontSize: '13px', fontWeight: '500',
                                            background: autoAnswer.isCompleting ? 'linear-gradient(135deg, #4FC3F7 0%, #29B6F6 100%)' : 'linear-gradient(135deg, #03A9F4 0%, #0288D1 100%)',
                                            color: '#FFFEF7'}">
                                {{ autoAnswer.isCompleting ? '停止自动完成' : '开始自动完成' }}
                            </button>

                            <button @click="autoAnswer.toggleAutoSave()"
                                    :style="{width: '100%', padding: '10px', border: 'none', borderRadius: '8px', cursor: 'pointer', fontSize: '13px', fontWeight: '500',
                                            background: autoAnswer.autoSave ? 'linear-gradient(135deg, #F57C00 0%, #E65100 100%)' : 'linear-gradient(135deg, #FF9800 0%, #FB8C00 100%)',
                                            color: '#FFFEF7'}">
                                {{ autoAnswer.autoSave ? '关闭自动保存' : '开启自动保存' }}
                            </button>
                        </div>

                        <!-- 状态显示 -->
                        <div v-if="autoAnswer.currentStatus" style="padding: 10px 12px; background: linear-gradient(135deg, #E8F5E9 0%, #C8E6C9 100%); border-radius: 10px; margin-bottom: 12px;">
                            <div style="font-size: 12px; color: #2E7D32; margin-bottom: 4px;">{{ autoAnswer.currentStatus }}</div>
                            <div style="font-size: 11px; color: #558B2F;">已完成: {{ autoAnswer.answeredCount }} / {{ autoAnswer.totalQuestions }}</div>
                        </div>

                        <!-- 日志 -->
                        <div v-if="autoAnswer.logs.length > 0" style="padding: 10px 12px; background: #F5F5F5; border-radius: 10px; max-height: 120px; overflow-y: auto;">
                            <div style="font-size: 11px; color: #666; margin-bottom: 6px; font-weight: 600;">日志</div>
                            <div v-for="(log, index) in autoAnswer.logs.slice(0, 10)" :key="index"
                                 style="font-size: 10px; color: #888; padding: 2px 0; border-bottom: 1px solid #eee;">
                                <span style="color: #aaa;">{{ log.time }}</span> {{ log.msg }}
                            </div>
                        </div>

                    </div>

                    <!-- 课件列表标签页 -->
                    <div v-show="activeTab === 'list'" style="max-height: 350px; overflow-y: auto;">

                        <!-- 分类面板 -->
                        <div v-for="(data, category) in categorizedCourses" :key="category"
                             style="margin-bottom: 8px; border: 1px solid rgba(139,115,85,0.15); border-radius: 10px; overflow: hidden; background: #FFFEF7;">

                            <!-- 分类头部 -->
                            <div @click="toggleCategory(category)"
                                 style="display: flex; justify-content: space-between; align-items: center; padding: 10px 12px; background: linear-gradient(135deg, #F8F6F0 0%, #F5F0E8 100%); cursor: pointer;">
                                <span style="font-weight: 600; color: #8B7355; font-size: 13px;">
                                    {{category === '课件' ? '📖' : category === '讨论' ? '💬' : category === '测验' ? '📝' : category === '作业' ? '📋' : '📁'}} {{category}}
                                    <span v-if="category === '课件'" style="font-size: 11px; color: #A99880;">
                                        ({{data.completed}}/{{data.total}})
                                    </span>
                                    <span v-else style="font-size: 11px; color: #A99880;">({{data.items.length}})</span>
                                </span>
                                <span style="color: #A99880; font-size: 12px;">{{expandedCategories[category] ? '▼' : '▶'}}</span>
                            </div>

                            <!-- 分类内容 -->
                            <div v-show="expandedCategories[category]" style="padding: 8px;">
                                <div v-for="item in data.items" :key="item.title"
                                     style="display: flex; justify-content: space-between; align-items: center; padding: 8px 10px; margin-bottom: 4px; background: #F8F6F0; border-radius: 8px;">

                                    <div style="display: flex; align-items: center; flex: 1; overflow: hidden;">
                                        <!-- 状态图标 -->
                                        <span v-if="category === '课件'"
                                              :style="{width: '8px', height: '8px', borderRadius: '50%', marginRight: '8px',
                                                      background: item.status === '已完成' ? '#90B77D' : item.status === '半完成' ? '#FFAB76' : '#E57373'}">
                                        </span>
                                        <span style="font-size: 12px; color: #8B7355; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
                                            {{item.title}}
                                        </span>
                                        <!-- 讨论回复状态 -->
                                        <span v-if="category === '讨论'"
                                              :style="{marginLeft: '8px', fontSize: '10px', padding: '2px 6px', borderRadius: '8px',
                                                      background: item.replyStatus === '已回复' ? 'rgba(144,183,125,0.2)' : 'rgba(229,115,115,0.2)',
                                                      color: item.replyStatus === '已回复' ? '#90B77D' : '#E57373'}">
                                            {{item.replyStatus || '未回复'}}
                                        </span>
                                    </div>

                                    <div style="display: flex; gap: 4px;">
                                        <button @click="jumpToCourse(item)"
                                                style="padding: 3px 8px; background: #7EC8E3; color: #FFFEF7; border: none; border-radius: 6px; font-size: 11px; cursor: pointer;">
                                            跳转
                                        </button>
                                        <!-- 讨论单独回复按钮 -->
                                        <button v-if="category === '讨论'" @click="discussionReply.performAutoReply(item)"
                                                style="padding: 3px 8px; background: #90B77D; color: #FFFEF7; border: none; border-radius: 6px; font-size: 11px; cursor: pointer;">
                                            回复
                                        </button>
                                    </div>
                                </div>
                            </div>
                        </div>

                    </div>

                    <!-- 设置标签页 -->
                    <div v-show="activeTab === 'settings'">

                        <!-- 视频倍速设置 -->
                        <div style="margin-bottom: 16px; padding: 14px; background: linear-gradient(135deg, #F8F6F0 0%, #F5F0E8 100%); border-radius: 12px;">
                            <label style="display: block; margin-bottom: 8px; font-weight: 600; color: #8B7355; font-size: 13px;">🎬 视频播放倍速</label>
                            <select v-model="settings.videoSpeed.value" @change="settings.saveVideoSpeed"
                                    style="width: 100%; padding: 10px; border: 1px solid rgba(139,115,85,0.2); border-radius: 8px; font-size: 13px; background: #FFFEF7; color: #8B7355;">
                                <option :value="1">1x 正常速度</option>
                                <option :value="2">2x 两倍速</option>
                                <option :value="3">3x 三倍速</option>
                            </select>
                        </div>

                        <!-- 说明 -->
                        <div style="padding: 14px; background: linear-gradient(135deg, #E8F5E9 0%, #F1F8E9 100%); border-radius: 12px; border: 1px solid rgba(144,183,125,0.2);">
                            <div style="font-weight: 600; color: #6B8E5F; margin-bottom: 8px; font-size: 13px;">🌱 使用说明</div>
                            <div style="font-size: 12px; color: #8B7355; line-height: 1.8;">
                                1. 点击「开始智能学习」<br>
                                2. 自动播放视频/PPT<br>
                                3. 完成后自动继续下一个<br>
                                4. 全部完成会提示
                            </div>
                        </div>

                    </div>

                </div>

                <!-- 底部信息 -->
                <div style="padding: 12px 20px; background: linear-gradient(135deg, #F8F6F0 0%, #F5F0E8 100%); border-top: 1px solid rgba(139,115,85,0.1); text-align: center;">
                    <div style="font-size: 11px; color: #A99880;">
                        Written By Abstract | 反馈群:1006332809
                    </div>
                </div>
            </div>
        `
        });
    }

    // ===============================
    // 视频控制器(PPT处理)
    // ===============================

    if (window.location.hostname === IFRAME_PAGE_HOST) {
        // PPT自动翻页处理(iframe中)
        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 > 0) {
                        window.parent.postMessage({
                            type: 'pptProgress',
                            progress: width
                        }, '*');
                    }

                    if (width >= 100 && !hasReportedCompletion) {
                        hasReportedCompletion = true;
                        clearInterval(pptIntervalId);
                        console.log('[PPT-iframe] PPT翻页完成,通知主页面');
                        window.parent.postMessage({
                            type: 'pptCompleted',
                            status: 'completed',
                            timestamp: Date.now()
                        }, '*');
                        return;
                    }
                    if (width < 100 && nextButton) {
                        simulateClick(nextButton);
                    }
                }
            }, checkInterval);

            // 超时处理
            setTimeout(() => {
                if (!hasReportedCompletion) {
                    hasReportedCompletion = true;
                    clearInterval(pptIntervalId);
                    window.parent.postMessage({
                        type: 'pptCompleted',
                        status: 'completed',
                        timestamp: Date.now()
                    }, '*');
                }
            }, 120000);
        }

        initPptAutoPaging();
    }

    // ===============================
    // 初始化应用
    // ===============================

    // 检查是否在主页面(支持多种域名格式)
    const isMainPage = window.location.hostname === MAIN_PAGE_HOST ||
                       (window.location.hostname.endsWith('.cqooc.com') &&
                        window.location.hostname !== IFRAME_PAGE_HOST) ||
                        window.location.hostname.endsWith('.smartedu.cn');

    console.log('[学习助手] 当前域名:', window.location.hostname);
    console.log('[学习助手] 是否主页面:', isMainPage);

    // PPT完成消息处理
    let pptResolveCallback = null;

    if (isMainPage) {
        // 监听iframe消息(PPT完成通知)
        window.addEventListener('message', (event) => {
            if (event.origin !== `https://${IFRAME_PAGE_HOST}`) return;
            const data = event.data;
            if (!data || !data.type) return;

            if (data.type === 'pptCompleted') {
                console.log('[学习助手] PPT完成通知已收到');
                if (pptResolveCallback) {
                    pptResolveCallback();
                    pptResolveCallback = null;
                }
            } else if (data.type === 'pptProgress') {
                console.log('[学习助手] PPT进度:', data.progress);
            }
        }, false);

        // 等待Vue加载完成
        const waitForVue = () => {
            // 尝试多种方式检测Vue
            const VueObj = window.Vue || (typeof Vue !== 'undefined' ? Vue : null);

            if (VueObj && VueObj.createApp) {
                console.log('[学习助手] Vue已加载,开始初始化');

                // 确保Vue在全局可用(模板编译需要)
                window.Vue = VueObj;

                // 直接使用检测到的Vue对象
                createApp = VueObj.createApp;
                ref = VueObj.ref;
                computed = VueObj.computed;
                onMounted = VueObj.onMounted;
                reactive = VueObj.reactive;
                console.log('[学习助手] Vue API已解构');

                try {
                    // 检查是否已存在容器
                    let appContainer = document.getElementById('vue-learning-assistant');
                    if (appContainer) {
                        console.log('[学习助手] 容器已存在,跳过创建');
                        return;
                    }

                    // 创建Vue应用容器
                    appContainer = document.createElement('div');
                    appContainer.id = 'vue-learning-assistant';
                    document.body.appendChild(appContainer);
                    console.log('[学习助手] 容器已创建');

                    // 创建并挂载Vue应用
                    const app = createVueApp();
                    app.mount('#vue-learning-assistant');

                    console.log('🎉 智能学习助手Vue3版本已启动');
                } catch (error) {
                    console.error('[学习助手] 应用初始化失败:', error);
                }
            } else {
                setTimeout(waitForVue, 100);
            }
        };

        // 确保DOM加载完成后再初始化
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', waitForVue);
        } else {
            waitForVue();
        }

        // 自动视频处理(保持兼容)
        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') ||
                                           node.querySelector('.dplayer-video-wrap') ||
                                           (node.classList && node.classList.contains('dplayer-video-wrap') ? node : null);
                        if (videoPlayer && !videoPlayer.dataset.autoplayInitialized) {
                            videoPlayer.dataset.autoplayInitialized = 'true';
                            const video = videoPlayer.querySelector('video');
                            if (video) {
                                setTimeout(() => {
                                    const playbackRate = parseFloat(localStorage.getItem('videoPlaybackSpeed')) || 3;
                                    video.playbackRate = playbackRate;
                                    video.muted = true;
                                    video.play().catch(console.error);
                                }, 500);
                            }
                        }

                        // 直接检测video元素
                        const directVideo = node.tagName === 'VIDEO' ? node : node.querySelector('video.dplayer-video');
                        if (directVideo && !directVideo.dataset.autoplayInitialized) {
                            directVideo.dataset.autoplayInitialized = 'true';
                            setTimeout(() => {
                                const playbackRate = parseFloat(localStorage.getItem('videoPlaybackSpeed')) || 3;
                                directVideo.playbackRate = playbackRate;
                                directVideo.muted = true;
                                directVideo.play().catch(console.error);
                            }, 500);
                        }
                    }
                });
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

})();