宜宾智慧校园助手

智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案,能够跳过秒看教学视频,自动阅读文档

当前为 2025-04-23 提交的版本,查看 最新版本

// ==UserScript==
// @name         宜宾智慧校园助手
// @namespace    智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案===来自计算机科学与技术学院--修改自若离智慧校园
// @version      12.22
// @description  智慧校园,解决宜宾学院智慧校园的题目,能够自动获取宜宾学院的智慧校园的作业的答案,能够跳过秒看教学视频,自动阅读文档
// @author       计算机科学与技术学院---软工
// @match        https://mooc.yibinu.edu.cn/*
// @icon         https://pic.imgdb.cn/item/673c85b1d29ded1a8ce8b97c.png
// @require      https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js
// @require      https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/ant-design-vue/1.7.8/antd.min.js
// @require      https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/xlsx/0.18.5/xlsx.full.min.js
// @require      https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/4.1.1/crypto-js.min.js
// @resource     ANTD_CSS https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/ant-design-vue/1.7.8/antd.min.css
// @run-at       document-end
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        GM_getResourceText
// ==/UserScript==

// 脚本设置对象
const setting = {
    logs: [
        '初始化脚本完成,',
        '当前脚本版本:V12.22',
        '由于国内无法访问gf.qytechs.cn,可以进入 https://gf.qytechs.cn/zh-CN 和https://home.gf.qytechs.cn.cn/ (版本更新较慢)下载更新脚本'
    ], // 日志数据
    datas: [], // 答案数据
    secretKey: '你好', // 默认密钥
    _vt: '274c8b3f2a8c63ffc960dd1e4e3f0eac',
    // 答题设置 - 默认值
    autoSubmit: false,  // 默认不自动提交答案
    autoEnterExam: true, // 默认自动进入考试
    // 学习进度
    learningProgress: {
        isLearning: false,
        currentChapter: null,
        currentContent: null,
        timestamp: null
    },
    // 初始化设置
    init() {
        // 尝试从localStorage加载设置
        try {
            const savedConfig = localStorage.getItem('examConfig');
            if (savedConfig) {
                const config = JSON.parse(savedConfig);
                this.autoSubmit = config.autoSubmit !== undefined ? config.autoSubmit : false;
                this.autoEnterExam = config.autoEnterExam !== undefined ? config.autoEnterExam : true;
            }
        } catch (e) {
            console.error('加载答题配置失败:', e);
            // 使用默认值
            this.autoSubmit = false;
            this.autoEnterExam = true;
        }
    }
};

// 初始化设置
setting.init();

// 资源加载管理器
const ResourceLoader = {
    resources: {
        styles: [
            {
                name: 'ANTD_CSS',
                type: 'resource'
            }
        ],
        scripts: [
            {
                name: 'vue',
                url: 'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/vue/2.6.14/vue.min.js'
            },
            {
                name: 'antd',
                url: 'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/ant-design-vue/1.7.8/antd.min.js'
            },
            {
                name: 'xlsx',
                url: 'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/xlsx/0.18.5/xlsx.full.min.js'
            },
            {
                name: 'crypto-js',
                url: 'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/crypto-js/4.1.1/crypto-js.min.js'
            }
        ]
    },

    // 资源加载状态
    loadStatus: new Map(),

    // 初始化加载
    async init() {
        try {
            // 先加载样式资源
            await this.loadStyles();
            // 再加载脚本资源
            await this.loadScripts();

            console.log('所有资源加载完成');
            return true;
        } catch (error) {
            console.error('资源加载失败:', error);
            return false;
        }
    },

    // 加载样式资源
    async loadStyles() {
        for (const style of this.resources.styles) {
            try {
                if (style.type === 'resource') {
                    // 使用GM_getResourceText加载资源
                    const cssContent = GM_getResourceText(style.name);
                    if (cssContent) {
                        GM_addStyle(cssContent);
                        this.loadStatus.set(style.name, true);
                        console.log(`样式资源 ${style.name} 加载成功`);
                    } else {
                        throw new Error(`无法获取样式资源 ${style.name}`);
                    }
                } else {
                    // 直接通过URL加载
                    await this.loadStyle(style.name, style.url);
                }
            } catch (error) {
                console.error(`加载样式 ${style.name} 失败:`, error);
                this.loadStatus.set(style.name, false);
            }
        }
    },

    // 加载脚本资源
    async loadScripts() {
        const promises = this.resources.scripts.map(script =>
            this.loadScript(script.name, script.url)
        );
        return Promise.all(promises);
    },

    // 加载单个样式
    loadStyle(name, url) {
        return new Promise((resolve, reject) => {
                const link = document.createElement('link');
                link.rel = 'stylesheet';
                link.href = url;

                link.onload = () => {
                    this.loadStatus.set(name, true);
                console.log(`样式 ${name} 加载成功`);
                    resolve();
                };

            link.onerror = (error) => {
                console.error(`样式 ${name} 加载失败:`, error);
                    this.loadStatus.set(name, false);
                    reject(new Error(`样式 ${name} 加载失败`));
                };

                document.head.appendChild(link);
        });
    },

    // 加载单个脚本
    loadScript(name, url) {
        return new Promise((resolve, reject) => {
            // 检查是否已加载
            if (window[name]) {
                this.loadStatus.set(name, true);
                resolve();
                return;
            }

            const script = document.createElement('script');
            script.src = url;
            script.async = true;

            script.onload = () => {
                this.loadStatus.set(name, true);
                console.log(`脚本 ${name} 加载成功`);
                resolve();
            };

            script.onerror = () => {
                // 加载失败时尝试备用CDN
                const backupUrl = this.getBackupUrl(url);
                if (backupUrl) {
                    script.src = backupUrl;
                    console.log(`尝试使用备用CDN加载 ${name}`);
                } else {
                    this.loadStatus.set(name, false);
                    console.error(`脚本 ${name} 加载失败`);
                    reject(new Error(`脚本 ${name} 加载失败`));
                }
            };

            document.head.appendChild(script);
        });
    },

    // 获取备用CDN地址
    getBackupUrl(url) {
        const cdnMap = {
            'lf26-cdn-tos.bytecdntp.com': 'cdn.jsdelivr.net/npm',
            'cdn.jsdelivr.net': 'cdnjs.cloudflare.com/ajax/libs',
            'cdnjs.cloudflare.com': 'unpkg.com'
        };

        for (const [current, backup] of Object.entries(cdnMap)) {
            if (url.includes(current)) {
                return url.replace(current, backup);
            }
        }
        return null;
    },

    // 检查资源是否都已加载
    checkAllLoaded() {
        return Array.from(this.loadStatus.values()).every(status => status);
    },

    // 获取加载失败的资源
    getFailedResources() {
        return Array.from(this.loadStatus.entries())
            .filter(([, status]) => !status)
            .map(([name]) => name);
    }
};

// 浏览器兼容性检查和处理
const BrowserCompatibility = {
    // 必需的特性列表
    requiredFeatures: {
        localStorage: {
            name: 'localStorage',
            test: () => typeof localStorage !== 'undefined',
            fallback: this.createMemoryStorage
        },
        promise: {
            name: 'Promise',
            test: () => typeof Promise !== 'undefined',
            fallback: () => this.loadPolyfill('promise-polyfill')
        },
        fetch: {
            name: 'fetch',
            test: () => typeof fetch !== 'undefined',
            fallback: () => this.loadPolyfill('whatwg-fetch')
        },
        customElements: {
            name: 'Custom Elements',
            test: () => 'customElements' in window,
            fallback: () => this.loadPolyfill('@webcomponents/custom-elements')
        }
    },

    // 浏览器信息
    browserInfo: {
        name: '',
        version: '',
        isSupported: false
    },

    // 初始化
    async init() {
        this.detectBrowser();
        const compatibility = await this.checkCompatibility();

        if (!compatibility.isCompatible) {
            this.showCompatibilityWarning(compatibility.unsupportedFeatures);
            await this.loadFallbacks(compatibility.unsupportedFeatures);
        }

        return compatibility.isCompatible;
    },

    // 检测浏览器信息
    detectBrowser() {
        const userAgent = navigator.userAgent;
        let browserName = "未知浏览器";
        let browserVersion = "未知版本";

        // 检测主流浏览器
        if (userAgent.indexOf("Chrome") > -1) {
            browserName = "Chrome";
            browserVersion = userAgent.match(/Chrome\/([0-9.]+)/)[1];
        } else if (userAgent.indexOf("Firefox") > -1) {
            browserName = "Firefox";
            browserVersion = userAgent.match(/Firefox\/([0-9.]+)/)[1];
        } else if (userAgent.indexOf("Safari") > -1) {
            browserName = "Safari";
            browserVersion = userAgent.match(/Version\/([0-9.]+)/)[1];
        } else if (userAgent.indexOf("MSIE") > -1 || userAgent.indexOf("Trident") > -1) {
            browserName = "Internet Explorer";
            browserVersion = userAgent.match(/(?:MSIE |rv:)([0-9.]+)/)[1];
        }

        this.browserInfo = {
            name: browserName,
            version: browserVersion,
            isSupported: this.checkBrowserSupport(browserName, browserVersion)
        };
    },

    // 检查浏览器是否支持
    checkBrowserSupport(name, version) {
        const minVersions = {
            'Chrome': 49,
            'Firefox': 45,
            'Safari': 10,
            'Internet Explorer': 11
        };

        const majorVersion = parseInt(version.split('.')[0]);
        return majorVersion >= (minVersions[name] || 0);
    },

    // 检查特性兼容性
    async checkCompatibility() {
        const unsupportedFeatures = [];

        for (const [feature, {test}] of Object.entries(this.requiredFeatures)) {
            if (!test()) {
                unsupportedFeatures.push(feature);
            }
        }

        return {
            isCompatible: unsupportedFeatures.length === 0,
            unsupportedFeatures
        };
    },

    // 加载polyfill
    async loadPolyfill(packageName) {
        const polyfillUrl = `https://cdn.jsdelivr.net/npm/${packageName}`;
        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = polyfillUrl;
            script.onload = resolve;
            script.onerror = reject;
            document.head.appendChild(script);
        });
    },

    // 创建内存存储的fallback
    createMemoryStorage() {
        const storage = {};
        return {
            setItem: (key, value) => storage[key] = value,
            getItem: (key) => storage[key],
            removeItem: (key) => delete storage[key],
            clear: () => Object.keys(storage).forEach(key => delete storage[key])
        };
    },

    // 加载所有需要的fallback
    async loadFallbacks(unsupportedFeatures) {
        const fallbackPromises = unsupportedFeatures.map(feature => {
            const {fallback} = this.requiredFeatures[feature];
            return fallback();
        });

        try {
            await Promise.all(fallbackPromises);
            console.log('所有fallback加载完成');
        } catch (error) {
            console.error('加载fallback失败:', error);
        }
    },

    // 显示兼容性警告
    showCompatibilityWarning(unsupportedFeatures) {
        const warning = document.createElement('div');
        warning.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            background: #fff3cd;
            color: #856404;
            padding: 12px;
            text-align: center;
            z-index: 9999;
            border-bottom: 1px solid #ffeeba;
        `;

        warning.innerHTML = `
            <strong>浏览器兼容性警告</strong><br>
            您的浏览器 (${this.browserInfo.name} ${this.browserInfo.version}) 可能不完全支持本脚本的所有功能。<br>
            建议使用最新版本的Chrome、Firefox或Safari浏览器。
        `;

        document.body.appendChild(warning);
    }
};

// 在脚本初始化时使用
async function initScript() {
    try {
        // 检查浏览器兼容性
        await BrowserCompatibility.init();

        // 加载资源
        await ResourceLoader.init();

        // 如果所有检查都通过,继续初始化脚本
        if (BrowserCompatibility.browserInfo.isSupported && ResourceLoader.checkAllLoaded()) {
            initView();
            // 初始化全局静音功能
            setTimeout(() => {
                initGlobalMute();
            }, 1000); // 延迟1秒执行,确保页面已完全加载
        } else {
            console.error('脚本初始化失败:', {
                browser: BrowserCompatibility.browserInfo,
                failedResources: ResourceLoader.getFailedResources()
            });
        }
    } catch (error) {
        console.error('脚本初始化错误:', error);
    }
}

// 启动脚本
initScript();

// 时间值
function decryptValidDuration() {
    try {
        const validDurations = {

            'c51ce410c124a10e0db5e4b97fc2af39': 86400000,

            '274c8b3f2a8c63ffc960dd1e4e3f0eac': 172800000,

            'e2ef524fbf3d9fe611d5a8e90fefdc9c': 259200000,

            '069059b7ef840f0c74a814ec9237b6ec': 432000000,

            '7f6ffaa6bb0b408017b62254211691b5': 604800000,

            '149e9677a5989fd342ae44213df68868': 2592000000
        };

        return validDurations[setting._vt] || 172800000; // 默认返回2天
    } catch (e) {
        console.error('解密时间值出错:', e);
        return 172800000; // 解密出错时返回默认值(2天)
    }
}

// 简化的验证时间管理
function setValidTime() {
    try {
        const validDuration = decryptValidDuration();
        const validUntil = Date.now() + validDuration;
        const data = {
            time: validUntil,
            hash: CryptoJS.SHA256(validUntil.toString()).toString()
        };
        localStorage.setItem('scriptValidUntil', JSON.stringify(data));
        return true;
    } catch (e) {
        console.error('设置验证时间出错:', e);
        return false;
    }
}

// 检查验证时间
function checkValidTime() {
    try {
        const data = localStorage.getItem('scriptValidUntil');
        if (!data) return false;

        const { time, hash } = JSON.parse(data);
        const now = Date.now();

        // 验证时间和哈希
        if (time && hash &&
            hash === CryptoJS.SHA256(time.toString()).toString() &&
            time > now) {
            return true;
        }

        localStorage.removeItem('scriptValidUntil');
        return false;
    } catch (e) {
        console.error('检查验证时间出错:', e);
        localStorage.removeItem('scriptValidUntil');
        return false;
    }
}

// 将验证函数定义为全局函数
window.verifySecret = function() {
    const input = document.getElementById('secretInput');
    if (!input) {
        console.error('找不到输入框元素');
        return;
    }

    const inputValue = input.value.trim();
    if (!inputValue) {
        input.style.borderColor = '#ff4d4f';
        input.style.animation = 'shake 0.5s';
        setTimeout(() => {
            input.style.borderColor = '#e8e8e8';
            input.style.animation = '';
        }, 1000);
        return;
    }

    if (inputValue !== setting.secretKey) {
        const modalDiv = document.querySelector('#secretModal > div');
        if (modalDiv) {
            modalDiv.style.animation = 'shake 0.5s';
            input.style.borderColor = '#ff4d4f';
            setTimeout(() => {
                modalDiv.style.animation = '';
                input.style.borderColor = '#e8e8e8';
            }, 1000);
        }
        return;
    }

    try {
        // 设置验证时间
        if (!setValidTime()) {
            throw new Error('设置验证时间失败');
        }

        // 添加关闭动画
        const modal = document.getElementById('secretModal');
        if (modal) {
            modal.style.animation = 'modalFadeOut 0.3s ease';
            setTimeout(() => {
                modal.remove();

                // 在验证成功后显示答题设置窗口
                setTimeout(() => {
                    // 创建答题设置窗口,传递true表示是首次使用
                    createInitialSettingsModal(true);
                }, 300);

                // 添加成功提示
                if (window.vue) {
                    window.vue.$message.success('验证成功!请先进行答题设置');
                }
            }, 300);
        }
    } catch (error) {
        console.error('验证过程出错:', error);
        if (window.vue) {
            window.vue.$message.error('验证过程出错,请刷新页面重试');
        }
    }
};

// 添加一个新的首次设置窗口函数
function createInitialSettingsModal(isFirstTime = true) {
    // 清除可能存在的旧模态框
    const oldModal = document.getElementById('settingsModal');
    if (oldModal) {
        document.body.removeChild(oldModal);
    }

    // 创建模态框容器
    const modalDiv = document.createElement('div');
    modalDiv.id = 'settingsModal';
    modalDiv.style.cssText = `
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.5);
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 10001;
    `;

    // 创建模态框内容
    const modalContent = document.createElement('div');
    modalContent.style.cssText = `
        background: white;
        border-radius: 4px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.15);
        width: 500px;
        max-width: 90%;
        position: relative;
    `;

    // 标题
    const modalHeader = document.createElement('div');
    modalHeader.style.cssText = `
        padding: 16px 24px;
        color: rgba(0, 0, 0, 0.85);
        background: #fff;
        border-bottom: 1px solid #f0f0f0;
        border-radius: 4px 4px 0 0;
        font-weight: 500;
        font-size: 18px;
    `;
    modalHeader.innerText = isFirstTime ? "首次使用 - 答题设置" : "答题设置";
    modalContent.appendChild(modalHeader);

    // 内容区域
    const modalBody = document.createElement('div');
    modalBody.style.cssText = `
        padding: 24px;
        font-size: 14px;
        line-height: 1.6;
        word-wrap: break-word;
    `;

    // 添加说明文字 (只在首次使用时显示)
    if (isFirstTime) {
        const description = document.createElement('div');
        description.style.cssText = `
            margin-bottom: 20px;
            padding: 12px;
            background-color: #f9f9f9;
            border-left: 4px solid #1890ff;
            border-radius: 2px;
        `;
        description.innerHTML = `
            <p>欢迎使用宜宾智慧校园助手!请先设置答题偏好,以下设置可稍后随时更改。</p>
        `;
        modalBody.appendChild(description);
    }

    // 创建设置项
    const autoSubmitDiv = document.createElement('div');
    autoSubmitDiv.style.cssText = `
        margin-bottom: 20px;
        padding: 15px;
        border: 1px solid #f0f0f0;
        border-radius: 4px;
        background-color: #fafafa;
    `;

    const autoSubmitCheckbox = document.createElement('input');
    autoSubmitCheckbox.type = 'checkbox';
    autoSubmitCheckbox.id = 'autoSubmitSetting';
    autoSubmitCheckbox.checked = setting.autoSubmit;
    autoSubmitCheckbox.style.cssText = `
        margin-right: 8px;
        margin-top: 3px;
        transform: scale(1.2);
    `;

    const autoSubmitLabel = document.createElement('label');
    autoSubmitLabel.htmlFor = 'autoSubmitSetting';
    autoSubmitLabel.style.fontWeight = 'bold';
    autoSubmitLabel.innerHTML = `
        自动提交答案
        <div style="font-weight: normal; font-size: 13px; color: #666; margin-top: 8px; line-height: 1.5;">
            <p>启用后,脚本将在完成所有题目作答后<b>自动提交</b>答卷并处理确认对话框。</p>
            <p>关闭后,脚本会填写答案但<b>不会自动提交</b>,让您有机会检查答案后手动提交。</p>
            <p>推荐设置:关闭 <span style="color: #ff4d4f;">(默认已关闭)</span></p>
        </div>
    `;

    autoSubmitDiv.appendChild(autoSubmitCheckbox);
    autoSubmitDiv.appendChild(autoSubmitLabel);
    modalBody.appendChild(autoSubmitDiv);

    // 自动进入考试设置
    const autoEnterExamDiv = document.createElement('div');
    autoEnterExamDiv.style.cssText = `
        margin-bottom: 16px;
        padding: 15px;
        border: 1px solid #f0f0f0;
        border-radius: 4px;
        background-color: #fafafa;
    `;

    const autoEnterExamCheckbox = document.createElement('input');
    autoEnterExamCheckbox.type = 'checkbox';
    autoEnterExamCheckbox.id = 'autoEnterExamSetting';
    autoEnterExamCheckbox.checked = setting.autoEnterExam;
    autoEnterExamCheckbox.style.cssText = `
        margin-right: 8px;
        margin-top: 3px;
        transform: scale(1.2);
    `;

    const autoEnterExamLabel = document.createElement('label');
    autoEnterExamLabel.htmlFor = 'autoEnterExamSetting';
    autoEnterExamLabel.style.fontWeight = 'bold';
    autoEnterExamLabel.innerHTML = `
        自动进入考试
        <div style="font-weight: normal; font-size: 13px; color: #666; margin-top: 8px; line-height: 1.5;">
            <p>启用后,脚本将自动点击"开始考试"或"继续答题"按钮,节省操作步骤。</p>
            <p>关闭后,需要手动点击按钮进入考试页面。</p>
            <p>推荐设置:开启 <span style="color: #52c41a;">(默认已开启)</span></p>
        </div>
    `;

    autoEnterExamDiv.appendChild(autoEnterExamCheckbox);
    autoEnterExamDiv.appendChild(autoEnterExamLabel);
    modalBody.appendChild(autoEnterExamDiv);

    modalContent.appendChild(modalBody);

    // 底部按钮
    const modalFooter = document.createElement('div');
    modalFooter.style.cssText = `
        padding: 10px 16px;
        text-align: right;
        background: transparent;
        border-top: 1px solid #f0f0f0;
        border-radius: 0 0 4px 4px;
    `;

    // 添加取消按钮(非首次使用时显示)
    if (!isFirstTime) {
        const cancelButton = document.createElement('button');
        cancelButton.className = 'ant-btn';
        cancelButton.style.cssText = `
            line-height: 1.5;
            display: inline-block;
            font-weight: 400;
            text-align: center;
            cursor: pointer;
            background-image: none;
            border: 1px solid #d9d9d9;
            white-space: nowrap;
            padding: 0 15px;
            font-size: 14px;
            border-radius: 4px;
            height: 32px;
            user-select: none;
            transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
            position: relative;
            color: rgba(0, 0, 0, 0.65);
            background-color: #fff;
            margin-right: 8px;
        `;
        cancelButton.innerText = "取消";
        cancelButton.onclick = function() {
            document.body.removeChild(modalDiv);
        };
        modalFooter.appendChild(cancelButton);
    }

    // 确定按钮
    const okButton = document.createElement('button');
    okButton.className = 'ant-btn ant-btn-primary';
    okButton.style.cssText = `
        line-height: 1.5;
        display: inline-block;
        font-weight: 400;
        text-align: center;
        cursor: pointer;
        background-image: none;
        border: 1px solid #1890ff;
        white-space: nowrap;
        padding: 0 15px;
        font-size: 14px;
        border-radius: 4px;
        height: 32px;
        user-select: none;
        transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
        position: relative;
        color: #fff;
        background-color: #1890ff;
    `;
    okButton.innerText = isFirstTime ? "确认并开始使用" : "保存设置";
    okButton.onclick = () => {
        try {
            // 获取设置值
            const autoSubmit = document.getElementById('autoSubmitSetting').checked;
            const autoEnterExam = document.getElementById('autoEnterExamSetting').checked;

            // 保存设置
            setting.autoSubmit = autoSubmit;
            setting.autoEnterExam = autoEnterExam;

            // 保存到localStorage
            localStorage.setItem('examConfig', JSON.stringify({
                autoSubmit,
                autoEnterExam
            }));

            // 首次使用时初始化脚本,否则显示成功提示
            if (isFirstTime) {
                // 继续初始化
                continueInit();

                // 成功提示
                if(window.vue) {
                    window.vue.$message.success('设置已保存,开始使用智慧校园助手');
                    log('首次设置已完成');
                }
            } else {
                // 正常使用时的提示
                if(window.vue) {
                    window.vue.$message.success('设置已保存');
                    log('已更新答题设置');
                }
            }

            // 关闭模态框
            document.body.removeChild(modalDiv);
        } catch (error) {
            console.error('保存设置出错:', error);
            // 出错提示
            if(window.vue) {
                window.vue.$message.error('保存失败,请刷新页面重试');
            }
            // 首次使用时,即使出错也继续初始化,使用默认设置
            if (isFirstTime) {
                continueInit();
            }
        }
    };

    modalFooter.appendChild(okButton);
    modalContent.appendChild(modalFooter);

    // 点击背景关闭模态框(非首次使用时才允许)
    if (!isFirstTime) {
        modalDiv.onclick = function(event) {
            if (event.target === modalDiv) {
                document.body.removeChild(modalDiv);
            }
        };
    }

    // 添加到body
    modalDiv.appendChild(modalContent);
    document.body.appendChild(modalDiv);

    // 添加动画效果
    modalContent.animate([
        { opacity: 0, transform: 'translateY(-20px)' },
        { opacity: 1, transform: 'translateY(0)' }
    ], { duration: 300, easing: 'ease-out' });
}

// 添加键盘事件监听器的函数
function addKeyboardListener() {
    document.addEventListener('keydown', function(event) {
        if (event.key === 'Enter') {
            const secretInput = document.getElementById('secretInput');
            if (secretInput && document.activeElement === secretInput) {
                verifySecret();
            }
        }
    });
}

// 日志
function log(logText){
    // 限制日志数量,防止内存占用过大
    if (setting.logs.length > 100) {
        setting.logs = setting.logs.slice(0, 50);
    }

    setting.logs.unshift(logText);

    // 使用Vue的响应式更新机制
    if (window.vue) {
        window.vue.logs = [...setting.logs];
    }
}

// 添加一个清理HTML标签的函数
function cleanHtmlTags(text) {
    if (!text) return '';

    // 将HTML转换为纯文本
    let temp = document.createElement('div');
    temp.innerHTML = text;
    let cleanText = temp.textContent || temp.innerText;

    // 清理多余的空白字符
    cleanText = cleanText.replace(/\s+/g, ' ').trim();

    return cleanText;
}

// 从后台获取答案
function getAnswer(url, data){
    log('获取答案中');
    let id = url.match(/\/examSubmit\/(\d+)\/getExamPaper/)[1];
    GM_xmlhttpRequest({
        method: "post",
        url: url,
        data: data,
        dataType: 'json',
        headers: {
            'Origin': location.origin,
            'User-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36',
            'Content-type': 'application/x-www-form-urlencoded;charset=utf-8',
            'Referer': `https://mooc.yibinu.edu.cn/examTest/stuExamList/${id}.mooc`
        },
        onload: function(res){
            if(res.status == 200){
                try {
                    let response = JSON.parse(res.responseText);
                    if (response && response.paper && response.paper.paperStruct) {
                        log("获取答案成功,正在格式化答案!");
                        formatAnswer(response.paper.paperStruct);
                    } else {
                        log("答案数据格式异常:" + JSON.stringify(response));
                        if (window.vue) {
                            window.vue.hasAnswer = false;
                        }
                    }
                } catch (error) {
                    log("解析答案数据失败:" + error.message);
                    if (window.vue) {
                        window.vue.hasAnswer = false;
                    }
                }
            } else {
                log("获取答案失败,状态码:" + res.status);
            }
        },
        onerror: function(error) {
            log("求答案失败:" + error.message);
        }
    });
}
//格式化答案
function formatAnswer(str) {
    try {
        setting.datas = []; // 清空之前的数据
        if (!Array.isArray(str)) {
            log("答案数据格式错误:期望数组类型");
            if (window.vue) {
                window.vue.hasAnswer = false;
            }
            return;
        }

        str.forEach((listItem, index) => {
            if (!listItem.quiz) {
                return;
            }

            // 使用cleanHtmlTags清理题目内容
            var question = cleanHtmlTags(listItem.quiz.quizContent) || "未知题目";
            var options = {};
            var optionContents = {};  // 存储选项内容
            var answer = [];
            const questionNum = (index + 1).toString();

            // 处理选择题
            if (listItem.quiz.quizOptionses && listItem.quiz.quizOptionses.length > 0) {
                listItem.quiz.quizOptionses.forEach((optionItem, idx) => {
                    if (optionItem && optionItem.optionId !== undefined) {
                        const optionLabel = String.fromCharCode(65 + idx);
                        options[optionItem.optionId] = optionLabel;
                        optionContents[optionItem.optionId] = optionItem.optionContent || '';
                    }
                });

                // 处理答案
                if (listItem.quiz.quizResponses) {
                    listItem.quiz.quizResponses.forEach(answerItem => {
                        if (answerItem && options[answerItem.optionId]) {
                            const label = options[answerItem.optionId];
                            const content = optionContents[answerItem.optionId];
                            answer.push(`${label}.${content}`);
                        }
                    });
                }

                // 并序号和选项标签
                const answerLabels = listItem.quiz.quizResponses
                    .map(item => options[item.optionId])
                    .join('');
                const idAndOptions = `${questionNum}.${answerLabels}`;

                setting.datas.push({
                    'key': index.toString(),
                    'idAndOptions': idAndOptions,
                    'question': question,
                    'answer': answer.join('\n'),  // 每个选项答案换行显示
                    'originalIndex': index // 保存原始索引,用于后续排序
                });
            } else {
                // 处理填空题
                if (listItem.quiz.quizResponses) {
                    const fillAnswers = [];
                    listItem.quiz.quizResponses.forEach(answerItem => {
                        if (answerItem && answerItem.responseContent) {
                            fillAnswers.push(answerItem.responseContent);
                        }
                    });

                    setting.datas.push({
                        'key': index.toString(),
                        'idAndOptions': `${questionNum}.(填空)`,
                        'question': question,
                        'answer': fillAnswers.join('\n'),  // 多个填空答案换行显示
                        'originalIndex': index // 保存原始索引,用于后续排序
                    });
                }
            }
        });

        // 提取题目编号信息(如果有)
        setting.datas.forEach(item => {
            // 尝试从题目中提取编号
            const numberMatch = item.question.match(/^(\d+)[、..]\s*/);
            if (numberMatch) {
                item.questionNumber = numberMatch[1];
                // 存储不带编号的题目文本,用于后续匹配
                item.cleanQuestion = item.question.replace(/^\d+[、..]\s*/, '').trim();
            } else {
                item.cleanQuestion = item.question;
            }
        });

        // 获取当前页面上的题目顺序
        const pageQuestions = [];
        const questionContainers = document.querySelectorAll('.view-test');
        if (questionContainers && questionContainers.length > 0) {
            questionContainers.forEach((container, idx) => {
                const textElement = container.querySelector('.test-text-tutami');
                if (textElement) {
                    const questionText = textElement.textContent.trim();
                    pageQuestions.push({
                        index: idx,
                        text: questionText
                    });
                }
            });

            log(`页面上找到 ${pageQuestions.length} 道题目,准备排序答案列表`);

            // 如果页面上有题目,则根据页面题目顺序排序答案列表
            if (pageQuestions.length > 0) {
                const sortedDatas = [];
                const usedAnswerIndices = new Set();

                // 第一轮:尝试为每个页面题目找到最匹配的答案
                pageQuestions.forEach((pageQuestion, pageIdx) => {
                    let bestMatchIndex = -1;
                    let bestMatchScore = 0;

                    // 遍历所有答案,找到最匹配的
                    setting.datas.forEach((answerData, answerIdx) => {
                        if (usedAnswerIndices.has(answerIdx)) return; // 跳过已使用的答案

                        const cleanPageQuestion = cleanHtmlTags(pageQuestion.text);
                        const cleanAnswerQuestion = answerData.cleanQuestion;

                        // 计算匹配分数
                        let matchScore = 0;
                        if (cleanPageQuestion.includes(cleanAnswerQuestion) ||
                            cleanAnswerQuestion.includes(cleanPageQuestion)) {
                            matchScore = Math.min(cleanPageQuestion.length, cleanAnswerQuestion.length) /
                                        Math.max(cleanPageQuestion.length, cleanAnswerQuestion.length);
                        }

                        // 如果是更好的匹配,则更新
                        if (matchScore > bestMatchScore) {
                            bestMatchScore = matchScore;
                            bestMatchIndex = answerIdx;
                        }
                    });

                    // 如果找到匹配,则添加到排序后的列表
                    if (bestMatchIndex !== -1 && bestMatchScore > 0.5) { // 设置一个阈值,确保匹配质量
                        sortedDatas.push(setting.datas[bestMatchIndex]);
                        usedAnswerIndices.add(bestMatchIndex);
                    }
                });

                // 第二轮:添加未匹配的答案到列表末尾
                setting.datas.forEach((answerData, idx) => {
                    if (!usedAnswerIndices.has(idx)) {
                        sortedDatas.push(answerData);
                    }
                });

                // 如果成功排序,则更新数据
                if (sortedDatas.length > 0) {
                    setting.datas = sortedDatas;
                    log(`答案列表已按当前题目顺序排序`);
                }
            }
        }

        // 更新 Vue 实例中的数据
        if (window.vue && setting.datas.length > 0) {
            // 更新idAndOptions以反映新的顺序
            setting.datas.forEach((item, idx) => {
                const questionNum = (idx + 1).toString();
                // 提取原始idAndOptions中的选项部分
                const optionsPart = item.idAndOptions.split('.').slice(1).join('.');
                item.idAndOptions = `${questionNum}.${optionsPart}`;
                item.key = idx.toString(); // 更新key以匹配新顺序
            });

            window.vue.answerList = [...setting.datas];
            window.vue.hasAnswer = true; // 设置答案获取状态为 true
        }

        log(`成功处理 ${setting.datas.length} 道题目`);
        log('答案获取完成,可以切换到答案列表查看');
    } catch (error) {
        log("格式化答案时出错:" + error.message);
        if (window.vue) {
            window.vue.hasAnswer = false;
        }
    }
}
//初始化界面
function initView(){
    // 检查验证是否有效
    if (checkValidTime()) {
        // 验证仍然有效,直接继续初始化
        continueInit();
        return;
    }

    // 创建验证界面的HTML
    const createModal = () => {
        const modalHtml = `
            <div id="secretModal" style="
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: rgba(0, 0, 0, 0.5);
                display: flex;
                justify-content: center;
                align-items: center;
                z-index: 10000;
            ">
                <div style="
                    background: white;
                    padding: 30px;
                    border-radius: 15px;
                    box-shadow: 0 8px 24px rgba(0,0,0,0.2);
                    width: 320px;
                    text-align: center;
                    animation: modalFadeIn 0.3s ease;
                ">
                    <img src="https://pic.imgdb.cn/item/673c85b1d29ded1a8ce8b97c.png" style="
                        width: 64px;
                        height: 64px;
                        margin-bottom: 15px;
                    ">
                    <h2 style="
                        margin: 0 0 20px 0;
                        color: #333;
                        font-size: 20px;
                        font-weight: 500;
                    ">请输入暗号---你好</h2>
                    <input type="text" id="secretInput" style="
                        width: 100%;
                        padding: 12px;
                        margin-bottom: 15px;
                        border: 2px solid #e8e8e8;
                        border-radius: 8px;
                        font-size: 16px;
                        outline: none;
                        transition: all 0.3s;
                        box-sizing: border-box;
                    " placeholder="请输入暗号...">
                    <button id="verifyButton" style="
                        width: 100%;
                        padding: 12px;
                        border: none;
                        background-color: #1890ff;
                        color: white;
                        border-radius: 8px;
                        font-size: 16px;
                        cursor: pointer;
                        transition: all 0.3s;
                        box-sizing: border-box;
                    ">验证</button>
                </div>
            </div>
        `;

        document.body.insertAdjacentHTML('beforeend', modalHtml);

        // 添加事件监听器
        const button = document.getElementById('verifyButton');
        if (button) {
            button.addEventListener('click', window.verifySecret);
        }

        // 添加键盘事件监听
        addKeyboardListener();

        // 自动聚焦输入框
        setTimeout(() => {
            const input = document.getElementById('secretInput');
            if (input) {
                input.focus();
            }
        }, 100);
    };

    // 添加动画样式
    const style = document.createElement('style');
    style.textContent = `
        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
            20%, 40%, 60%, 80% { transform: translateX(5px); }
        }
        @keyframes modalFadeIn {
            from { opacity: 0; transform: translateY(-20px); }
            to { opacity: 1; transform: translateY(0); }
        }
        @keyframes modalFadeOut {
            from { opacity: 1; transform: translateY(0); }
            to { opacity: 0; transform: translateY(-20px); }
        }
    `;
    document.head.appendChild(style);

    createModal();
}

// 将原来的初始化代码移动到新的函数中
function continueInit() {
    var $div =$('<div class="rlBox minimized">' +
        '   <a-card title="宜宾学院智慧校园助手" style="width: 100%;height: 100%;">' +
        '       <template slot="extra">' +
        '           <span v-show="!close" style="margin-right: 10px; font-size: 12px; color: #999;">{{validTimeRemaining}}</span>' +
        '           <a-button :type="buttonColor" shape="circle" :icon="buttonIcon" @click="toClose" size="small"/>' +
        '       </template>' +
        '       <div style="margin-bottom: 15px;" v-show="!close">' +
        '           <div class="button-container">' +
        '               <a-button :type="autoLearning ? \'danger\' : \'warning\'" class="main-button" @click="startAutoLearning">{{autoLearning ? "停止学习" : "自动学习"}}</a-button>' +
        '               <a-button type="danger" class="main-button" @click="clearProgress">清除进度</a-button>' +
        '               <a-button type="default" class="main-button" @click="showMoreMenu">' +
        '                   <span>更多功能</span>' +
        '                   <a-icon type="down" />'+
        '               </a-button>' +
        '           </div>' +
        '       </div>' +
        '       <a-tabs default-active-key="1" @change="callback" v-show="!close">' +
        '           <a-tab-pane key="1" tab="运行日志">' +
        '               <div class="rl-panel log">' +
        '                   <p v-for="item in logs" class="log_content">' +
        '                       {{item}}' +
        '                   </p>' +
        '               </div>' +
        '           </a-tab-pane>' +
        '           <a-tab-pane key="2" :tab="answerTabTitle" :disabled="!hasAnswer">' +
        '               <div class="rl-panel">' +
        '                   <a-table id="rlTable"' +
        '                   :pagination="false" bordered size="small" :columns="columns" :data-source="answerList">' +
        '                   </a-table>' +
        '               </div>' +
        '           </a-tab-pane>' +
        '       </a-tabs>' +
        '   </a-card>' +
        '</div>');

    // 更新样式
    const customStyle = `
        .rlBox {
            position: fixed;
            top: 10px;
            right: 10px;
            width: 400px;
            z-index: 9999;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 10px;
            transition: all 0.3s ease;
            transform: none !important;
            overflow: hidden;
            backdrop-filter: blur(10px);
            -webkit-backdrop-filter: blur(10px);
            background-color: rgba(255, 255, 255, 0.95);
        }

        /* 卡片标题美化 */
        .ant-card-head {
            border-bottom: 1px solid rgba(0, 0, 0, 0.06);
            padding: 0 12px;
            background: linear-gradient(to right, #f5f5f5, #ffffff);
            border-radius: 8px 8px 0 0;
        }

        .ant-card-head-title {
            font-weight: 600;
            color: #1890ff;
            font-size: 16px;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
        }

        /* 按钮动画效果 */
        .main-button {
            width: 100%;
            height: 38px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 4px;
            font-size: 14px;
            font-weight: 500;
            box-shadow: 0 2px 0 rgba(0,0,0,0.05);
            transition: all 0.3s;
            position: relative;
            overflow: hidden;
        }

        .main-button:after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 5px;
            height: 5px;
            background: rgba(255, 255, 255, 0.5);
            opacity: 0;
            border-radius: 100%;
            transform: scale(1, 1) translate(-50%);
            transform-origin: 50% 50%;
        }

        .main-button:hover:after {
            animation: ripple 0.6s ease-out;
        }

        @keyframes ripple {
            0% {
                transform: scale(0, 0);
                opacity: 0.5;
            }
            20% {
                transform: scale(25, 25);
                opacity: 0.3;
            }
            100% {
                opacity: 0;
                transform: scale(40, 40);
            }
        }

        /* 滚动条美化 */
        .rl-panel::-webkit-scrollbar {
            width: 6px;
            height: 6px;
        }

        .rl-panel::-webkit-scrollbar-thumb {
            background: #c0c0c0;
            border-radius: 3px;
            transition: all 0.3s;
        }

        .rl-panel::-webkit-scrollbar-thumb:hover {
            background: #a0a0a0;
        }

        .rl-panel::-webkit-scrollbar-track {
            background: #f0f0f0;
            border-radius: 3px;
        }

        /* 日志内容美化 */
        .log_content {
            margin: 6px 0;
            padding: 6px 10px;
            border-radius: 4px;
            background: #f9f9f9;
            border-left: 3px solid #1890ff;
            transition: all 0.2s;
            animation: fade-in-log 0.3s ease-out backwards;
        }

        .log_content:nth-child(odd) {
            background: #f5f5f5;
            border-left-color: #52c41a;
        }

        .log_content:hover {
            background: #f0f7ff;
            transform: translateX(2px);
        }

        @keyframes fade-in-log {
            from { opacity: 0; transform: translateY(5px); }
            to { opacity: 1; transform: translateY(0); }
        }

        /* 优化最小化状态 */
        .rlBox.minimized {
            width: 40px !important;
            height: 40px !important;
            padding: 0 !important;
            overflow: hidden;
            opacity: 0.8;
            cursor: pointer;
            border-radius: 50%;
            background: #1890ff;
            box-shadow: 0 4px 12px rgba(24, 144, 255, 0.3);
            transition: all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
            transform: scale(1) !important;
        }

        /* 最小化状态悬停效果 */
        .rlBox.minimized:hover {
            opacity: 1;
            box-shadow: 0 6px 16px rgba(24, 144, 255, 0.5);
            transform: scale(1.1) !important;
        }

        /* 展开状态动画 */
        .rlBox:not(.minimized) {
            animation: expand-box 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
            box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
            border: 1px solid rgba(0, 0, 0, 0.06);
        }

        @keyframes expand-box {
            0% {
                opacity: 0.8;
                width: 40px;
                height: 40px;
                border-radius: 50%;
                transform: scale(1);
            }
            60% {
                border-radius: 10px;
                opacity: 1;
            }
            100% {
                width: 400px;
                height: auto;
                opacity: 1;
                transform: scale(1);
            }
        }

        @keyframes minimize-box {
            0% {
                width: 400px;
                height: auto;
                border-radius: 8px;
                opacity: 1;
            }
            40% {
                opacity: 0.9;
                border-radius: 25px;
            }
            100% {
                width: 40px;
                height: 40px;
                border-radius: 50%;
                opacity: 0.8;
            }
        }

        /* 按钮容器样式 */
        .button-container {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 8px;
            width: 100%;
            animation: fade-in 0.3s ease-out 0.1s backwards;
        }

        @keyframes fade-in {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        /* 主按钮样式 */
        .main-button {
            width: 100%;
            height: 38px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 4px;
            font-size: 14px;
            font-weight: 500;
            box-shadow: 0 2px 0 rgba(0,0,0,0.05);
            transition: all 0.3s;
        }

        /* 按钮样式优化 */
        .ant-btn-danger {
            background: #ff4d4f !important;
            border-color: #ff4d4f !important;
            color: white !important;
        }

        .ant-btn-danger:hover {
            background: #ff7875 !important;
            border-color: #ff7875 !important;
        }

        .ant-btn-primary {
            background: #1890ff !important;
            border-color: #1890ff !important;
        }

        .ant-btn-primary:hover {
            background: #40a9ff !important;
            border-color: #40a9ff !important;
        }

        .ant-btn-success {
            background: #52c41a !important;
            border-color: #52c41a !important;
            color: white !important;
        }

        .ant-btn-success:hover {
            background: #73d13d !important;
            border-color: #73d13d !important;
        }

        .ant-btn-warning {
            background: #faad14 !important;
            border-color: #faad14 !important;
            color: white !important;
        }

        .ant-btn-warning:hover {
            background: #ffc53d !important;
            border-color: #ffc53d !important;
        }

        /* 下拉菜单样式 */
        .more-menu {
            position: fixed;
            background: white;
            border-radius: 4px;
            box-shadow: 0 3px 6px -4px rgba(0,0,0,0.12), 0 6px 16px 0 rgba(0,0,0,0.08), 0 9px 28px 8px rgba(0,0,0,0.05);
            z-index: 10000;
            display: none;
            padding: 4px 0;
        }

        .more-menu.show {
            display: block;
            animation: fadeIn 0.2s ease;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(-10px); }
            to { opacity: 1; transform: translateY(0); }
        }

        .menu-item {
            padding: 10px 16px;
            color: #333;
            cursor: pointer;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            width: 100%;
            box-sizing: border-box;
        }

        .menu-item:hover {
            background: #f5f5f5;
        }

        .menu-item i {
            margin-right: 8px;
            font-size: 14px;
        }

        .menu-divider {
            height: 1px;
            background: #f0f0f0;
            margin: 4px 0;
        }

        /* 最小化状态下的卡片样式 */
        .rlBox.minimized .ant-card {
            background: transparent;
            border: none;
            box-shadow: none;
        }

        /* 最小化状态下的标题隐藏 */
        .rlBox.minimized .ant-card-head-title {
            display: none;
        }

        /* 最小化状态下的开按钮样式 */
        .rlBox.minimized .ant-btn-circle {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: transparent !important;
            border: 2px solid white !important;
            color: white !important;
            box-shadow: none;
        }

        .rlBox.minimized .ant-btn-circle:hover {
            background: rgba(255, 255, 255, 0.2) !important;
        }

        /* 移动端适配 */
        @media screen and (max-width: 768px) {
            .rlBox {
                width: 300px;
            }

            .rlBox.minimized {
                width: 36px !important;
                height: 36px !important;
            }
        }

        /* 表格容器样式 */
        .rl-panel {
            height: auto;
            max-height: calc(100vh - 250px);
            overflow-y: auto;
            overflow-x: hidden;
        }

        /* 表格样式优化 */
        .ant-table-wrapper {
            overflow: visible;
        }

        .ant-table {
            min-width: 100%;
            background: transparent;
        }

        /* 美化滚动条样式 */
        .rl-panel::-webkit-scrollbar {
            width: 6px;
            height: 6px;
        }

        .rl-panel::-webkit-scrollbar-thumb {
            background: #d9d9d9;
            border-radius: 3px;
        }

        .rl-panel::-webkit-scrollbar-track {
            background: #f0f0f0;
            border-radius: 3px;
        }

        /* 表格单元格样式 */
        .ant-table-tbody > tr > td {
            white-space: normal;
            word-break: break-word;
            padding: 8px 16px;
            line-height: 1.5;
            max-width: 0;
        }

        /* 表格头部样式 */
        .ant-table-thead > tr > th {
            background: #f5f5f5;
            padding: 12px 16px;
            white-space: nowrap;
            position: sticky;
            top: 0;
            z-index: 2;
        }

        /* 保表格布局合理 */
        #rlTable {
            table-layout: fixed;
            width: 100%;
        }

        /* 移动端适配 */
        @media screen and (max-width: 768px) {
            .rl-panel {
                max-height: calc(100vh - 200px);
            }

            .ant-table-tbody > tr > td {
                padding: 6px 12px;
            }

            .ant-table-thead > tr > th {
                padding: 8px 12px;
            }
        }
    `;

    $("body").append($div);
    GM_addStyle(GM_getResourceText("cs1"));
    GM_addStyle(GM_getResourceText("cs2"));
    GM_addStyle(customStyle);

    // 创建更多菜单DOM
    const moreMenuHtml = `
        <div id="moreMenu" class="more-menu">
            <div class="menu-item" id="autoAnswerBtn">
                <i class="anticon anticon-check-circle"></i>自动答题
            </div>
            <div class="menu-item" id="videoSkipBtn">
                <i class="anticon anticon-forward"></i>秒过视频
            </div>
            <div class="menu-item" id="exportExcelBtn">
                <i class="anticon anticon-export"></i>导出题库
            </div>
            <div class="menu-item" id="clearLogsBtn">
                <i class="anticon anticon-delete"></i>清除日志
            </div>
            <div class="menu-divider"></div>
            <div class="menu-item" id="tutorialBtn">
                <i class="anticon anticon-question-circle"></i>使用教程
            </div>
            <div class="menu-item" id="settingsBtn">
                <i class="anticon anticon-setting"></i>答题设置
            </div>
        </div>
    `;
    $("body").append(moreMenuHtml);

    // 创建辅助函数用于教程模态框
    function createVNode(tag, props = {}, children = []) {
        const element = document.createElement(tag);

        // 设置属性
        for (const key in props) {
            if (key === 'style' && typeof props[key] === 'object') {
                Object.assign(element.style, props[key]);
            } else {
                element.setAttribute(key, props[key]);
            }
        }

        // 添加子元素
        if (Array.isArray(children)) {
            children.forEach(child => {
                if (typeof child === 'string') {
                    element.appendChild(document.createTextNode(child));
                } else {
                    element.appendChild(child);
                }
            });
        } else if (typeof children === 'string') {
            element.textContent = children;
        }

        return element;
    }

    function createText(text) {
        return document.createTextNode(text);
    }

    // Icon 组件简单实现
    function Icon(props) {
        const icon = document.createElement('i');
        icon.className = `anticon anticon-${props.type}`;
        if (props.theme) {
            icon.className += ` anticon-${props.type}-${props.theme}`;
        }
        if (props.style) {
            Object.assign(icon.style, props.style);
        }
        return icon;
    }

    // 手动定义直接绑定的事件处理函数
    window.autoAnswerHandler = function() {
        if (window.vue) window.vue.autoAnswer();
        document.getElementById('moreMenu').classList.remove('show');
    };

    window.videoSkipHandler = function() {
        if (window.vue) window.vue.videoSkip();
        document.getElementById('moreMenu').classList.remove('show');
    };

    window.exportExcelHandler = function() {
        if (window.vue) window.vue.exportExcel();
        document.getElementById('moreMenu').classList.remove('show');
    };

    window.clearLogsHandler = function() {
        if (window.vue) window.vue.clearLogs();
        document.getElementById('moreMenu').classList.remove('show');
    };

    window.openTutorialHandler = function() {
        if (window.vue) window.vue.showTutorial();
        document.getElementById('moreMenu').classList.remove('show');
    };

    window.openSettingsHandler = function() {
        if (window.vue) window.vue.openSettings();
        document.getElementById('moreMenu').classList.remove('show');
    };

    // 确保菜单项绑定了正确的事件处理函数
    const autoAnswerBtn = document.getElementById('autoAnswerBtn');
    const videoSkipBtn = document.getElementById('videoSkipBtn');
    const exportExcelBtn = document.getElementById('exportExcelBtn');
    const clearLogsBtn = document.getElementById('clearLogsBtn');
    const tutorialBtn = document.getElementById('tutorialBtn');
    const settingsBtn = document.getElementById('settingsBtn');

    if (autoAnswerBtn) autoAnswerBtn.addEventListener('click', window.autoAnswerHandler);
    if (videoSkipBtn) videoSkipBtn.addEventListener('click', window.videoSkipHandler);
    if (exportExcelBtn) exportExcelBtn.addEventListener('click', window.exportExcelHandler);
    if (clearLogsBtn) clearLogsBtn.addEventListener('click', window.clearLogsHandler);
    if (tutorialBtn) tutorialBtn.addEventListener('click', window.openTutorialHandler);
    if (settingsBtn) settingsBtn.addEventListener('click', window.openSettingsHandler);

    var vue = new Vue({
        el: '.rlBox',
        data:{
            logs: setting.logs,
            close: true,
            key: '1',
            columns:[
                {
                    title: '序号.选项',
                    dataIndex: 'idAndOptions',
                    key: 'idAndOptions',
                    width: '80px',
                    fixed: 'left',
                    align: 'center'
                },
                {
                    title: '题目',
                    dataIndex: 'question',
                    key: 'question',
                    width: '45%',
                    ellipsis: true
                },
                {
                    title: '答案',
                    dataIndex: 'answer',
                    key: 'answer',
                    width: '45%',
                    customRender: (text) => {
                        return text ? text.split('\n').join('<br/>') : '';
                    }
                }
            ],
            answerList: [],  // 初化为空数组
            isDragging: false,
            currentX: 0,
            currentY: 0,
            initialX: 0,
            initialY: 0,
            xOffset: 0,
            yOffset: 0,
            hasAnswer: false, // 添加答案获取状态标志
            validUntil: localStorage.getItem('scriptValidUntil') || null,
            autoLearning: false, // 添加自动学习状态标志
        },
        mounted() {
            window.vue = this;
            this.initDragEvents();

            // 修改初始化位置设置
            const box = document.querySelector('.rlBox');
            box.style.right = '0px';
            box.style.left = 'auto';
            box.setAttribute('data-expand-side', 'right');

            // 添加窗口大小改变监听
            window.addEventListener('resize', this.checkPosition);

            // 每分钟更新一次验证时间显示
            setInterval(() => {
                this.validUntil = localStorage.getItem('scriptValidUntil');
            }, 60000);

            // 检查是否需要恢复学习进度
            this.checkLearningProgress();

            // 添加页面URL变化监听
            this.initUrlChangeListener();
        },
        computed:{
            isShow(){
                return this.close ? 0.8 : 1.0;
            },
            buttonIcon(){
                return this.close ? 'plus' : 'minus';
            },
            buttonColor(){
                return this.close ? 'primary' : 'default';
            },
            answerTabTitle() {
                return this.hasAnswer ? '答案列表' : '答案列表 (等待获取...)';
            },
            validTimeRemaining() {
                const validTime = getValidTime();
                if (!validTime) return '未验证';

                const remaining = validTime - Date.now();
                if (remaining <= 0) return '验证已过期';

                const days = Math.floor(remaining / (24 * 60 * 60 * 1000));
                const hours = Math.floor((remaining % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
                return `验证剩余: ${days}天${hours}小时`;
            }
        },
        methods: {
            callback(key) {
                if (key === '2' && !this.hasAnswer) {
                    this.$message.warning('请等待答案获取完成后再查看答案列表');
                    this.key = '1'; // 保持在日志页面
                    return;
                }
                this.key = key;
            },
            toClose() {
                this.close = !this.close;
                const box = document.querySelector('.rlBox');
                const rect = box.getBoundingClientRect();
                const windowWidth = window.innerWidth;

                if (this.close) {
                    // 最小化时,判断靠近哪边
                    const centerX = rect.left + rect.width / 2;

                    // 添加最小化动画类
                    box.style.animation = 'minimize-box 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards';

                    // 在动画执行过程中保持原位置
                    box.style.transition = 'none';

                    if (centerX > windowWidth / 2) {
                        // 靠右
                        box.style.right = '10px';
                        box.style.left = 'auto';
                        box.setAttribute('data-side', 'right');
                    } else {
                        // 靠左
                        box.style.left = '10px';
                        box.style.right = 'auto';
                        box.setAttribute('data-side', 'left');
                    }

                    // 使用setTimeout确保类名在动画结束后添加
                    setTimeout(() => {
                        box.classList.add('minimized');
                        // 恢复transition以保证后续hover效果
                        box.style.animation = '';
                        box.style.transition = 'all 0.4s cubic-bezier(0.34, 1.56, 0.64, 1)';
                    }, 400);
                } else {
                    // 展开时,先移除最小化类,然后应用展开动画
                    box.classList.remove('minimized');

                    const side = box.getAttribute('data-side') || 'right';
                    if (side === 'right') {
                        box.style.right = '10px';
                        box.style.left = 'auto';
                    } else {
                        box.style.left = '10px';
                        box.style.right = 'auto';
                    }

                    // 为内部内容添加循序渐入效果
                    const tabs = box.querySelector('.ant-tabs');
                    const buttons = box.querySelector('.button-container');

                    if (tabs) {
                        tabs.style.opacity = '0';
                        tabs.style.transform = 'translateY(10px)';
                        tabs.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
                        tabs.style.display = '';

                        setTimeout(() => {
                            tabs.style.opacity = '1';
                            tabs.style.transform = 'translateY(0)';
                        }, 100);
                    }

                    if (buttons) {
                        buttons.style.opacity = '0';
                        buttons.style.transform = 'translateY(10px)';
                        buttons.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
                        buttons.style.display = '';

                        setTimeout(() => {
                            buttons.style.opacity = '1';
                            buttons.style.transform = 'translateY(0)';
                        }, 50);
                    }
                }
            },
            startAutoLearning() {
                if(this.autoLearning) {
                    this.autoLearning = false;
                    localStorage.removeItem('learningProgress');
                    log("已停止自动学习");
                    this.$message.info("已停止自动学习");
                    return;
                }

                this.autoLearning = true;
                this.$message.success({
                    content: "自动学习已启动",
                    duration: 3,
                    description: "系统将自动完成视频观看、文档阅读和测验答题"
                });
                log("开始自动学习...");
                this.processCurrentContent();
            },
            processCurrentContent() {
                if(!this.autoLearning) {
                    log("自动学习已停止");
                    return;
                }

                const pageType = checkPageType();
                if(!pageType) {
                    log("未识别到当前内容类型,等待加载...");
                    setTimeout(() => this.processCurrentContent(), 1000);
                    return;
                }

                const currentTab = document.querySelector('.tab-active .tab-inner');
                const itemName = currentTab.getAttribute('itemname');
                const currentChapter = document.querySelector('.nav-text.current');
                const chapterName = currentChapter ? currentChapter.querySelector('.node-text').textContent.trim() : '未知章节';

                // 显示当前学习内容提示
                this.$message.info({
                    content: `正在处理: ${itemName}`,
                    duration: 3,
                    description: `章节: ${chapterName}`
                });

                log(`正在处理 ${chapterName} - ${itemName} (${pageType})`);

                // 根据页面类型执行不同操作
                switch(pageType) {
                    case 'video':
                    this.handleVideo();
                        break;
                    case 'document':
                    this.handleDocument();
                        break;
                    case 'quiz':
                        // 使用全局函数而不是方法
                        handleQuiz();
                        break;
                }
            },
            handleVideo() {
                let video = document.getElementsByTagName("video")[0];
                if(!video) {
                    log("当前页面不存在视频,请确保视频已加载");
                    setTimeout(() => this.handleVideo(), 1000);
                    return;
                }

                // 显示视频处理提示
                this.$message.info({
                    content: "正在处理视频",
                    duration: 3,
                    description: "系统将自动完成视频观看"
                });

                // 尝试使用HTML5视频API静音
                video.muted = true;

                // 尝试使用JWPlayer API静音(如果存在)
                try {
                    if (typeof jwplayer === 'function' && jwplayer("mediaplayer")) {
                        jwplayer("mediaplayer").setMute(true);
                        log("已使用JWPlayer API静音视频");
                    } else {
                        log("已自动静音HTML5视频");
                    }
                } catch (error) {
                    log("JWPlayer静音尝试失败,使用HTML5静音: " + error.message);
                }

                video.addEventListener('ended', () => {
                    if(this.autoLearning) {
                        log("视频播放完成,准备切换下一个内容");
                        this.$message.success({
                            content: "视频学习完成",
                            duration: 2
                        });
                        this.switchToNextContent();
                    }
                });

                try {
                    if (video.duration && !isNaN(video.duration)) {
                        video.currentTime = video.duration - 0.1;
                        video.playbackRate = 1;
                        log("正在完成当前视频...");
                    } else {
                        log("等待视频加载...");
                        video.addEventListener('loadedmetadata', () => {
                            video.currentTime = video.duration - 0.1;
                            video.playbackRate = 1;
                            log("视频加载完成,正在处理...");
                        });
                    }
                } catch (error) {
                    log("处理视频时出错:" + error.message);
                }
            },
            handleDocument() {
                const totalPages = parseInt(document.querySelector('.flexpaper_lblTotalPages')?.textContent.replace('/ ', '')) || 0;

                if(totalPages === 0) {
                    log("未检测到文档页数,请确保文档已加载");
                    setTimeout(() => this.handleDocument(), 1000);
                    return;
                }

                // 计算阅读时间和翻页间隔
                let totalReadingTime, pageInterval;

                if(totalPages < 10) {
                    // 小于10页文档,使用固定1秒1页的速度
                    totalReadingTime = totalPages;
                    pageInterval = 1000; // 1秒1页
                } else if(totalPages > 50) {
                    // 超过50页文档,固定30秒完成
                    totalReadingTime = 30;
                    pageInterval = Math.max(totalReadingTime / totalPages * 1000, 300); // 每页间隔时间(毫秒),最小300ms
                } else {
                    // 10-50页文档使用原有逻辑
                    totalReadingTime = totalPages > 20 ? 20 : 10; // 超过20页固定20秒,否则10秒
                    pageInterval = Math.max(totalReadingTime / totalPages * 1000, 300); // 每页间隔时间(毫秒),最小300ms
                }

                // 显示文档阅读提示
                this.$message.info({
                    content: "开始阅读文档",
                    duration: 3,
                    description: `共 ${totalPages} 页,预计用时 ${totalReadingTime} 秒`
                });

                log(`正在阅读文档,共${totalPages}页,预计用时${totalReadingTime}秒,翻页间隔${Math.round(pageInterval)}毫秒`);
                let currentPage = 1;

                const readInterval = setInterval(() => {
                    if(!this.autoLearning || currentPage >= totalPages) {
                        clearInterval(readInterval);
                        if(this.autoLearning) {
                            log(`文档阅读完成,准备切换到下一个内容`);
                            this.$message.success({
                                content: "文档阅读完成",
                                duration: 2
                            });
                            this.switchToNextContent();
                        }
                        return;
                    }

                    try {
                        const nextButton = document.querySelector('.flexpaper_bttnPrevNext');
                        if(nextButton) {
                            nextButton.click();
                            // 每5页或翻页速度快时每10页显示一次进度
                            const progressInterval = pageInterval < 500 ? 10 : 5;
                            if(currentPage % progressInterval === 0) {
                                this.$message.info({
                                    content: `阅读进度: ${Math.round((currentPage/totalPages) * 100)}%`,
                                    duration: 1
                                });
                            }
                            log(`正在阅读第${currentPage}页,共${totalPages}页`);
                            currentPage++;
                        } else {
                            log("未找到翻页按钮,尝试重新加载");
                            setTimeout(() => this.handleDocument(), 1000);
                        }
                    } catch (error) {
                        log(`翻页过程出错: ${error.message}`);
                        clearInterval(readInterval);
                        setTimeout(() => this.handleDocument(), 1000);
                    }
                }, pageInterval);
            },
            switchToNextContent() {
                if(!this.autoLearning) return;

                // 获取所有标签页
                const tabs = document.querySelectorAll('.tab-inner');
                let currentTabIndex = -1;

                // 找到当前激活的标签页
                tabs.forEach((tab, index) => {
                    if(tab.parentElement.classList.contains('tab-active')) {
                        currentTabIndex = index;
                    }
                });

                // 检查是否还有下一个内容
                if(currentTabIndex < tabs.length - 1) {
                    // 还有下一个内容,继续在当前章节学习
                    const nextTab = tabs[currentTabIndex + 1];
                    const nextTabName = nextTab.getAttribute('itemname');
                    log(`切换到下一个内容: ${nextTabName}`);
                    nextTab.click();

                    setTimeout(() => this.processCurrentContent(), 1500);
                } else {
                    // 当前章节的所有内容已学习完成
                    const currentChapter = document.querySelector('.nav-text.current');
                    if (!currentChapter) {
                        log("无法识别当前章节,自动学习已停止");
                        this.autoLearning = false;
                        return;
                    }

                    const chapterName = currentChapter.querySelector('.node-text')?.textContent.trim() || '未知章节';
                    log(`章节 ${chapterName} 的所有内容已学习完成,检查是否有下一讲...`);

                    // 查找当前章节的父元素(sup-item),然后检查是否有下一个讲
                    const currentSupItem = currentChapter.closest('.nav-item.sup-item');
                    if (!currentSupItem) {
                        log("无法找到当前章节的父元素,尝试切换到下一章节");
                        this.switchToNextChapter();
                        return;
                    }

                    // 获取当前章节下的子章节列表(二级菜单)
                    const subNav = currentSupItem.querySelector('.sub-nav');
                    if (!subNav || !subNav.children || subNav.children.length === 0) {
                        log("当前章节没有子章节,尝试切换到下一章节");
                        this.switchToNextChapter();
                        return;
                    }

                    // 检查子菜单是否已展开,如果没有则先展开
                    if (subNav.style.display === 'none') {
                        log("展开子菜单...");
                        subNav.style.display = 'block';
                        setTimeout(() => this.switchToNextContent(), 500);
                        return;
                    }

                    // 查找当前激活的讲次
                    const allLectures = Array.from(subNav.querySelectorAll('.sub-nav-text'));
                    if (allLectures.length === 0) {
                        log("未找到讲次列表,尝试切换到下一章节");
                        this.switchToNextChapter();
                        return;
                    }

                    // 查找当前激活的讲
                    let currentLectureIndex = -1;
                    for (let i = 0; i < allLectures.length; i++) {
                        if (allLectures[i].classList.contains('current')) {
                            currentLectureIndex = i;
                            break;
                        }
                    }

                    log(`当前是第 ${currentLectureIndex + 1} 讲,共 ${allLectures.length} 讲`);

                    // 检查是否有下一讲
                    if (currentLectureIndex < allLectures.length - 1) {
                        // 有下一讲,切换到下一讲
                        const nextLecture = allLectures[currentLectureIndex + 1];
                        const nextLectureName = nextLecture.textContent.trim();
                        log(`切换到下一讲: ${nextLectureName}`);

                        // 保存当前章节信息用于恢复
                        const progress = {
                            isLearning: true,
                            currentChapter: currentSupItem.getAttribute('id'),
                            nextLecture: nextLecture.getAttribute('id') || nextLecture.getAttribute('data-id'),
                            timestamp: Date.now(),
                            isPageSwitching: true
                        };
                        localStorage.setItem('learningProgress', JSON.stringify(progress));
                        setting.learningProgress = progress;

                        // 显示切换提示
                        this.$notification.info({
                            message: '准备切换讲次',
                            description: `即将切换到: ${nextLectureName}`,
                            duration: 3
                        });

                        // 点击下一讲
                        nextLecture.click();

                        // 等待内容加载完成后继续处理
                        setTimeout(() => {
                            try {
                                // 检查是否有内容标签
                                const tabList = document.querySelectorAll('.tab-inner');
                                if (!tabList || tabList.length === 0) {
                                    throw new Error("未找到可学习的内容");
                                }

                                const firstTab = tabList[0];
                                log(`开始学习新讲次内容: ${firstTab.getAttribute('itemname')}`);
                                firstTab.click();

                                // 确保自动学习状态保持开启
                                this.autoLearning = true;

                                // 保存新的学习进度
                                const newProgress = {
                                    isLearning: true,
                                    currentChapter: currentSupItem.getAttribute('id'),
                                    currentContent: firstTab.getAttribute('itemid'),
                                    timestamp: Date.now(),
                                    isPageSwitching: false
                                };
                                localStorage.setItem('learningProgress', JSON.stringify(newProgress));

                                // 等待内容加载完成后开始学习
                                setTimeout(() => {
                                    if (this.autoLearning) {
                                        log(`开始自动学习新讲次内容...`);
                                        this.processCurrentContent();
                                    }
                                }, 1500);
                            } catch (error) {
                                log(`加载讲次内容失败: ${error.message}`);
                        this.switchToNextChapter();
                            }
                        }, 2000);
                    } else {
                        // 已经是当前章节的最后一讲,切换到下一章节
                        log("当前章节的所有讲次已学习完成,准备切换到下一章节");
                        this.switchToNextChapter();
                    }
                }
            },
            switchToNextChapter() {
                try {
                    const allChapters = document.querySelectorAll('.sidebar .nav-list .nav-item.sup-item');
                    if (!allChapters.length) {
                        this.autoLearning = false;
                        log("未找到章节列表,自动学习已停止");
                        this.$message.warning("未找到章节列表");
                        return;
                    }

                    log(`共发现 ${allChapters.length} 个章节`);

                    let currentChapterIndex = -1;
                    allChapters.forEach((chapter, index) => {
                        if(chapter.querySelector('.nav-text.current')) {
                            currentChapterIndex = index;
                        }
                    });

                    if(currentChapterIndex < allChapters.length - 1) {
                        const nextChapter = allChapters[currentChapterIndex + 1];
                        const nextChapterLink = nextChapter.querySelector('.nav-text');
                        const nextChapterName = nextChapter.querySelector('.node-text').textContent.trim();

                        if (!nextChapterLink) {
                            throw new Error("无法找到章节链接");
                        }

                        const unitId = nextChapterLink.getAttribute('unitid');
                        if (!unitId) {
                            throw new Error("无法获取章节ID");
                        }

                        // 设置进度信息,标记正在切换章节
                        const progress = {
                            isLearning: true,
                            currentChapter: unitId, // 设置为要跳转的章节ID
                            currentContent: null,
                            timestamp: Date.now(),
                            isPageSwitching: true // 标记正在切换页面
                        };
                        localStorage.setItem('learningProgress', JSON.stringify(progress));
                        setting.learningProgress = progress;

                        // 显示章节切换提示
                        this.$notification.info({
                            message: '准备切换章节',
                            description: `即将切换到: ${nextChapterName}`,
                            duration: 3
                        });

                        log(`准备切换到下一章节: ${nextChapterName} (${currentChapterIndex + 2}/${allChapters.length})`);

                        // 直接点击章节链接
                        nextChapterLink.click();

                        // 等待页面加载完成
                        setTimeout(() => {
                            try {
                                // 展开子章节列表
                                const subNav = nextChapter.querySelector('.sub-nav');
                                if (!subNav) {
                                    throw new Error("未找到子章节列表");
                                }
                                subNav.style.display = 'block';

                                // 获取第一个子章节
                                const firstSubChapter = subNav.querySelector('.sub-nav-text');
                                if (!firstSubChapter) {
                                    throw new Error("未找到子章节");
                                }

                                // 点击第一个子章节
                                log(`点击第一个子章节...`);
                                firstSubChapter.click();

                                // 等待子章节内容加载
                                setTimeout(() => {
                                    try {
                                        // 获取并点击第一个内容标签
                                        const tabList = document.querySelectorAll('.tab-inner');
                                        if (!tabList || tabList.length === 0) {
                                            throw new Error("未找到可学习的内容");
                                        }

                                        const firstTab = tabList[0];
                                        log(`开始学习: ${firstTab.getAttribute('itemname')}`);
                                        firstTab.click();

                                        // 确保自动学习状态保持开启
                                        this.autoLearning = true;

                                        // 保存新的学习进度
                                        const newProgress = {
                                            isLearning: true,
                                            currentChapter: unitId,
                                            currentContent: firstTab.getAttribute('itemid'),
                                            timestamp: Date.now()
                                        };
                                        localStorage.setItem('learningProgress', JSON.stringify(newProgress));

                                        // 等待内容加载完成后开始学习
                                        setTimeout(() => {
                                            if (this.autoLearning) {
                                                log(`开始自动学习新章节内容...`);
                                                this.processCurrentContent();
                                            }
                                        }, 1500);
                                    } catch (error) {
                                        throw new Error(`加载内容失败: ${error.message}`);
                                    }
                                }, 1500);
                            } catch (error) {
                                throw new Error(`切换子章节失败: ${error.message}`);
                            }
                        }, 2000);
                    } else {
                        this.autoLearning = false;
                        log("已完成所有章节的学习!");
                        this.$notification.success({
                            message: '学习完成',
                            description: '恭喜!已完成所有章节的学习',
                            duration: 0
                        });
                    }
                } catch (error) {
                    this.autoLearning = false;
                    log(`切换章节失败: ${error.message}`);
                    this.$message.error("切换章节失败,请刷新页面重试");
                }
            },
            checkPosition() {
                const box = document.querySelector('.rlBox');
                const rect = box.getBoundingClientRect();
                const windowWidth = window.innerWidth;
                const windowHeight = window.innerHeight;

                // 检查并修正水平位置
                if (rect.right > windowWidth) {
                    box.style.right = '0px';
                    box.style.left = 'auto';
                }
                if (rect.left < 0) {
                    box.style.left = '0px';
                    box.style.right = 'auto';
                }

                // 检查并修正垂直位置
                if (rect.bottom > windowHeight) {
                    box.style.top = `${windowHeight - rect.height - 10}px`;
                }
                if (rect.top < 0) {
                    box.style.top = '10px';
                }
            },
            autoAnswer() {
                log("开始自动答题...");

                // 检查是否已获取答案
                if (!setting.datas || setting.datas.length === 0) {
                    log("未找到答案信息,请先获取答案");
                    return;
                }

                log(`共发现 ${setting.datas.length} 道题目的答案`);
                let answeredCount = 0;

                // 获取所有题目容器
                const allQuestionContainers = document.querySelectorAll('.view-test');
                if (!allQuestionContainers || allQuestionContainers.length === 0) {
                    log("未找到题目容器,请确认是否在答题页面");
                    return;
                }

                log(`页面上共有 ${allQuestionContainers.length} 道题目`);

                // 遍历所有题目容器,确保每个题目都能找到对应的答案
                allQuestionContainers.forEach((questionContainer, containerIndex) => {
                    try {
                        // 获取题目文本,用于匹配答案
                        const questionTextElement = questionContainer.querySelector('.test-text-tutami');
                        if (!questionTextElement) {
                            log(`第 ${containerIndex + 1} 题未找到题目文本`);
                            return;
                        }

                        const questionText = questionTextElement.textContent.trim();

                        // 在答案列表中查找匹配的题目
                        let matchedAnswerData = null;
                        let matchIndex = -1;

                        // 首先尝试按索引匹配
                        if (containerIndex < setting.datas.length) {
                            matchedAnswerData = setting.datas[containerIndex];
                            matchIndex = containerIndex;
                        }

                        // 如果索引匹配失败或题目不匹配,则尝试通过题目内容匹配
                        if (!matchedAnswerData || !questionText.includes(cleanHtmlTags(matchedAnswerData.question))) {
                            // 在答案列表中查找匹配的题目
                            for (let i = 0; i < setting.datas.length; i++) {
                                const answerData = setting.datas[i];
                                const cleanQuestion = cleanHtmlTags(answerData.question);

                                // 检查题目文本是否匹配
                                if (questionText.includes(cleanQuestion) || cleanQuestion.includes(questionText)) {
                                    matchedAnswerData = answerData;
                                    matchIndex = i;
                                    break;
                                }
                            }
                        }

                        if (!matchedAnswerData) {
                            log(`第 ${containerIndex + 1} 题未找到匹配的答案`);
                            return;
                        }

                        // 获取匹配到的答案
                        const answer = matchedAnswerData.answer;
                        if (!answer) {
                            log(`第 ${containerIndex + 1} 题答案为空`);
                            return;
                        }

                        log(`第 ${containerIndex + 1} 题匹配到答案列表中的第 ${matchIndex + 1} 题`);

                        // 判断题目类型
                        const isMultiChoice = questionContainer.querySelector('.input-c') !== null;
                        const isSingleChoice = questionContainer.querySelector('.input-r') !== null;
                        const isFillBlank = questionContainer.querySelector('.fillblank') !== null;

                        if (isMultiChoice || isSingleChoice) {
                            // 处理选择题
                            const answerLetters = answer.split('\n').map(a => a.trim().charAt(0));
                            const options = questionContainer.querySelectorAll('.t-option');

                            options.forEach((option, idx) => {
                                const letter = String.fromCharCode(65 + idx);
                                if (answerLetters.includes(letter)) {
                                    // 查找选项的点击元素
                                    const clickTarget = option.querySelector('a[href="javascript:void(0)"]') ||
                                                      option.querySelector(isMultiChoice ? '.input-c' : '.input-r');

                                    if (clickTarget) {
                                        // 检查是否已经选中
                                        const isChecked = option.querySelector(isMultiChoice ? '.input-c.selected' : '.input-r.selected');
                                        if (!isChecked) {
                                            clickTarget.click();
                                            log(`第 ${containerIndex + 1} 题选择了选项 ${letter}`);
                                        }
                                    }
                                }
                            });
                            answeredCount++;
                        } else if (isFillBlank) {
                            // 处理填空题
                            const input = questionContainer.querySelector('.fillblank');
                            if (input) {
                                input.value = answer.replace(/^.*?\./,'').trim(); // 移除可能的选项标记
                                // 触发必要的事件
                                input.dispatchEvent(new Event('input', { bubbles: true }));
                                input.dispatchEvent(new Event('change', { bubbles: true }));
                                log(`第 ${containerIndex + 1} 题填写了答案: ${answer}`);
                                answeredCount++;
                            }
                        }
                    } catch (error) {
                        log(`第 ${containerIndex + 1} 题自动答题出错: ${error.message}`);
                    }
                });

                // 显示完成提示
                log(`自动答题完成!成功答题 ${answeredCount} 道题目`);
                this.$message.success(`自动答题完成!成功答题 ${answeredCount} 道题目,请检查后手动提交。`);
            },
            exportExcel(){
                // 检查是否有答案数据
                if (!this.answerList || this.answerList.length === 0) {
                    this.$message.error('没有可导出的答案数!请等待答案获取完成。');
                    log('导出失败:没有答案数据');
                    return;
                }

                // 检查xlsx库是否加载成功
                if (typeof XLSX === 'undefined') {
                    this.$message.info('正在加载XLSX库,请稍候...');
                    log('正在加载XLSX库...');

                    // 使用中国境内常用CDN (将第二个CDN放在首位)
                    const cdnList = [
                        'https://lib.baomitu.com/xlsx/0.18.5/xlsx.full.min.js',  // 360 前端静态资源库 (移到首位)
                        'https://cdn.bootcdn.net/ajax/libs/xlsx/0.18.5/xlsx.full.min.js',  // BootCDN
                        'https://fastly.jsdelivr.net/npm/[email protected]/dist/xlsx.full.min.js', // JSDelivr 的 Fastly CDN
                        'https://gcore.jsdelivr.net/npm/[email protected]/dist/xlsx.full.min.js', // JSDelivr 的 Gcore CDN
                        'https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/xlsx/0.18.5/xlsx.full.min.js' // 字节跳动 CDN
                    ];

                    let currentCdnIndex = 0;

                    const tryNextCDN = () => {
                        if (currentCdnIndex >= cdnList.length) {
                            log('所有CDN尝试失败,请刷新页面或稍后再试');
                            this.$message.error('加载失败,请刷新页面或稍后再试');
                            return;
                        }

                        const currentCdnUrl = cdnList[currentCdnIndex];
                        log(`尝试从 CDN (${currentCdnIndex + 1}/${cdnList.length}) 加载XLSX库...`);

                        const script = document.createElement('script');
                        script.src = currentCdnUrl;

                        script.onload = () => {
                            log('XLSX库加载成功,正在导出题库...');
                            // 库加载成功后直接执行导出,不需要用户再次点击
                            setTimeout(() => this.exportExcel(), 500);
                        };

                        script.onerror = () => {
                            log(`CDN ${currentCdnIndex + 1} 加载失败,尝试下一个...`);
                            currentCdnIndex++;
                            tryNextCDN();
                        };

                        document.head.appendChild(script);
                    };

                    // 开始尝试加载
                    tryNextCDN();
                    return;
                }

                // 提取题目开头的序号
                const extractQuestionNumber = (question) => {
                    // 匹配模式: 数字开头,后跟"、"或"."或":"等分隔符
                    const match = question.match(/^(\d+)[、.::]/);
                    if (match) {
                        return parseInt(match[1], 10);
                    }
                    return null;
                };

                // 对答案数据按题目开头的序号排序
                const sortedAnswers = [...this.answerList].sort((a, b) => {
                    const numA = extractQuestionNumber(a.question);
                    const numB = extractQuestionNumber(b.question);

                    // 如果两个都有序号,按序号排序
                    if (numA !== null && numB !== null) {
                        return numA - numB;
                    }

                    // 如果只有一个有序号,有序号的排前面
                    if (numA !== null) return -1;
                    if (numB !== null) return 1;

                    // 否则保持原有顺序
                    return 0;
                });

                // 准备数据(只保留题目和答案两列,原始序号从题目中提取)
                const data = sortedAnswers.map(item => {
                    return {
                        '题目': item.question,
                        '答案': item.answer
                    };
                });

                try {
                    // 创建工作簿
                    const wb = XLSX.utils.book_new();
                    // 创建工作表
                    const ws = XLSX.utils.json_to_sheet(data);

                    // 设置列宽
                    const colWidths = {
                        '题目': 70,
                        '答案': 50
                    };

                    ws['!cols'] = Object.keys(colWidths).map(key => ({
                        wch: colWidths[key]
                    }));

                    // 从页面提取题目名称和章节信息
                    let examName = '';
                    let chapterNum = '';
                    let lectureNum = '';

                    // 1. 尝试从tab栏获取测试题名称
                    const activeTab = document.querySelector('.tabs .tab-active');
                    if (activeTab) {
                        const tabLink = activeTab.querySelector('.tab-inner');
                        if (tabLink && tabLink.getAttribute('itemname')) {
                            examName = tabLink.getAttribute('itemname');
                        } else if (activeTab.getAttribute('title')) {
                            examName = activeTab.getAttribute('title');
                        }
                    }

                    // 如果找不到,从页面标题提取
                    if (!examName) {
                        examName = document.title.replace(/\s*[-—]\s*智慧校园.*$/, '').trim();
                    }

                    // 2. 提取章节数和讲数
                    // 从各种可能的元素中提取章节数
                    const extractChapterNum = (text) => {
                        if (!text) return '';
                        const match = text.match(/第([0-90-9一二三四五六七八九十]+)章/);
                        if (match) return match[1];
                        return '';
                    };

                    // 从各种可能的元素中提取讲数
                    const extractLectureNum = (text) => {
                        if (!text) return '';
                        const match = text.match(/第([0-90-9一二三四五六七八九十]+)讲/);
                        if (match) return match[1];
                        return '';
                    };

                    // 尝试从导航菜单提取
                    const navItems = document.querySelectorAll('.nav-text, .node-text');
                    for (const item of navItems) {
                        if (item.textContent.includes('章')) {
                            const num = extractChapterNum(item.textContent);
                            if (num) {
                                chapterNum = num;
                                // 检查是否是当前章节
                                const parent = item.closest('.nav-item');
                                if (parent && (parent.classList.contains('current') ||
                                    item.classList.contains('current') ||
                                    parent.querySelector('.current'))) {
                                    break; // 找到当前章节后停止
                                }
                            }
                        }
                    }

                    // 尝试从讲次导航提取
                    const subNavItems = document.querySelectorAll('.sub-nav-text');
                    for (const item of subNavItems) {
                        if (item.textContent.includes('讲')) {
                            const num = extractLectureNum(item.textContent);
                            if (num && item.classList.contains('current')) {
                                lectureNum = num;
                                break;
                            }
                        }
                    }

                    // 备选方法:从面包屑提取
                    if (!chapterNum || !lectureNum) {
                        const breadcrumbs = document.querySelectorAll('.breadcrumb a, .breadcrumb span, .breadcrumb li');
                        for (const crumb of breadcrumbs) {
                            if (!chapterNum && crumb.textContent.includes('章')) {
                                chapterNum = extractChapterNum(crumb.textContent);
                            }
                            if (!lectureNum && crumb.textContent.includes('讲')) {
                                lectureNum = extractLectureNum(crumb.textContent);
                            }
                        }
                    }

                    // 备选方法:从标题元素提取
                    if (!chapterNum || !lectureNum) {
                        const titleElements = document.querySelectorAll('h1, h2, h3, h4, .title, .chapter-title');
                        for (const elem of titleElements) {
                            if (!chapterNum && elem.textContent.includes('章')) {
                                chapterNum = extractChapterNum(elem.textContent);
                            }
                            if (!lectureNum && elem.textContent.includes('讲')) {
                                lectureNum = extractLectureNum(elem.textContent);
                            }
                        }
                    }

                    // 组合文件名前缀
                    let fileNamePrefix = '';
                    if (chapterNum) {
                        fileNamePrefix += `第${chapterNum}章`;
                        if (lectureNum) {
                            fileNamePrefix += `第${lectureNum}讲 `;
                        } else {
                            fileNamePrefix += ' ';
                        }
                    }

                    // 如果找不到测试题名称,则使用默认值
                    if (!examName || examName.length < 2) {
                        examName = '智慧校园题库';
                    }

                    // 组合文件名
                    let fileName = fileNamePrefix + examName;

                    // 清理文件名中的非法字符
                    fileName = fileName.replace(/[\\/:*?"<>|]/g, '_');

                    // 将工作表添加到工作簿 (使用文件名前30个字符作为工作表名)
                    let sheetName = fileName;
                    if (sheetName.length > 30) {
                        sheetName = sheetName.substring(0, 30);
                    }
                    XLSX.utils.book_append_sheet(wb, ws, sheetName);

                    // 生成并下载文件
                    XLSX.writeFile(wb, fileName + '.xlsx');

                    log(`题库已导出为: ${fileName}.xlsx`);
                    this.$message.success('题库导出成功!');
                } catch (error) {
                    log(`导出Excel出错: ${error.message}`);
                    this.$message.error(`导出失败: ${error.message}`);
                }
            },
            clearLogs() {
                // 清空所有现有日志
                this.logs = [];
                setting.logs = [];

                // 添加清除提示
                const clearMessage = [
                    '日志已清除',
                    '------------------------',

                ];

                // 直接设置新的日志数组,而不是使用 log 函数
                this.logs = clearMessage;
                setting.logs = [...clearMessage];

                // 阻止其他日志添加
                setTimeout(() => {
                    // 确保清除状态保持
                    if (this.logs.length > clearMessage.length) {
                        this.logs = [...clearMessage];
                        setting.logs = [...clearMessage];
                    }
                }, 200);
            },
            // 视频快速完成
            videoSkip() {
                const pageType = checkPageType();
                if (pageType !== 'video') {
                    this.$message.warning('当前页面不是视频页面,请在视频页面使用此功能');
                    log('秒过视频功能仅在视频页面有效');
                    return;
                }

                log('正在尝试秒过视频...');
                try {
                    // 尝试使用JWPlayer API
                    if (typeof jwplayer === 'function' && jwplayer("mediaplayer")) {
                        const jwp = jwplayer("mediaplayer");
                        // 设置静音
                        jwp.setMute(true);
                        log("已通过JWPlayer API静音视频");

                        // 获取视频时长并跳至结尾
                        const duration = jwp.getDuration() || 0;
                        if (duration > 0) {
                            jwp.seek(duration - 1);
                            log(`已将JWPlayer视频进度设置为结束位置(${Math.floor(duration)}秒)`);

                            setTimeout(() => {
                                log('JWPlayer视频即将自动结束,请等待系统记录完成状态');
                                this.$message.success('视频已跳至结尾,即将自动完成');
                            }, 500);
                            return;
                        }
                    }

                    // 尝试找到HTML5视频元素
                    const videoPlayer = document.querySelector('video');
                    if (!videoPlayer) {
                        log('未找到视频元素,请确认页面已完全加载');
                        this.$message.error('未找到视频元素,请刷新页面重试');
                        return;
                    }

                    // 设置视频当前时间为接近结尾
                    const duration = videoPlayer.duration || 0;
                    if (duration <= 0) {
                        log('无法获取视频时长,请等待视频加载完成');
                        this.$message.warning('请等待视频加载完成后再试');
                        return;
                    }

                    // 设置为视频末尾前几秒
                    videoPlayer.muted = true;
                    videoPlayer.currentTime = duration - 1;
                    log(`已将HTML5视频进度设置为结束位置(${Math.floor(duration)}秒)`);

                    // 模拟视频播放完成事件
                    setTimeout(() => {
                        videoPlayer.play();
                        log('视频即将自动结束,请等待系统记录完成状态');
                        this.$message.success('视频已跳至结尾,即将自动完成');
                    }, 500);
                } catch (error) {
                    log('秒过视频时出错: ' + error.message);
                    this.$message.error('秒过视频失败: ' + error.message);
                }
            },
            // 显示更多功能菜单
            showMoreMenu() {
                const menu = document.getElementById('moreMenu');
                if (!menu) {
                    console.error('菜单元素不存在');
                    return;
                }

                // 切换显示状态
                if (menu.classList.contains('show')) {
                    menu.classList.remove('show');
                } else {
                    // 确保菜单显示在正确位置
                    const button = document.querySelector('.button-container .main-button:nth-child(3)');
                    if (button) {
                        const rect = button.getBoundingClientRect();

                        // 设置菜单位置属性
                        menu.style.position = 'fixed';
                        menu.style.top = (rect.bottom + 2) + 'px';
                        menu.style.left = rect.left + 'px'; // 左对齐
                        menu.style.width = rect.width + 'px'; // 设置精确宽度与按钮相同
                        menu.style.right = 'auto'; // 清除之前的right值

                        // 添加阴影和过渡效果,提升视觉体验
                        menu.style.boxShadow = '0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)';
                        menu.style.transition = 'all 0.2s ease';

                        // 记录菜单位置,便于调试
                        console.log(`菜单位置: top=${menu.style.top}, left=${menu.style.left}, width=${menu.style.width}`);
                    }

                    // 先移除其他可能的事件监听器
                    document.removeEventListener('click', this.closeMenuHandler);

                    // 显示菜单
                    menu.classList.add('show');

                    // 存储关闭函数引用,以便之后可以正确移除
                    this.closeMenuHandler = (e) => {
                        if (!menu.contains(e.target) &&
                            !e.target.closest('.main-button:nth-child(3)')) {
                            menu.classList.remove('show');
                            document.removeEventListener('click', this.closeMenuHandler);
                        }
                    };

                    // 延迟添加事件监听,避免立即触发
                    setTimeout(() => {
                        document.addEventListener('click', this.closeMenuHandler);
                    }, 100);
                }
            },
            // 打开设置对话框
            openSettings() {
                // 直接调用详细设置对话框函数
                createInitialSettingsModal(false);
            },
            // 显示使用教程
            showTutorial() {
                try {
                    // 移除已有的模态框
                    const existingModals = document.querySelectorAll('#custom-tutorial-modal');
                    existingModals.forEach(modal => {
                        if (modal.parentNode) {
                            modal.parentNode.removeChild(modal);
                        }
                    });

                    // 创建自定义模态框(不依赖antd)
                    const modalHTML = `
                        <div id="custom-tutorial-modal" style="
                            position: fixed;
                            top: 0;
                            left: 0;
                            right: 0;
                            bottom: 0;
                            background-color: rgba(0, 0, 0, 0.5);
                            display: flex;
                            justify-content: center;
                            align-items: flex-start;
                            padding-top: 50px;
                            z-index: 100000;
                            animation: fadeIn 0.3s;
                        ">
                            <div style="
                                background-color: white;
                                width: 700px;
                                border-radius: 4px;
                                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                                display: flex;
                                flex-direction: column;
                                max-height: 80vh;
                                animation: slideDown 0.3s;
                            ">
                                <div style="
                                    padding: 16px;
                                    border-bottom: 1px solid #f0f0f0;
                                    display: flex;
                                    justify-content: space-between;
                                    align-items: center;
                                ">
                                    <h3 style="margin: 0; font-size: 16px;">宜宾智慧校园助手使用教程</h3>
                                    <button id="close-tutorial-button" style="
                                        border: none;
                                        background: none;
                                        font-size: 16px;
                                        cursor: pointer;
                                        color: #999;
                                    ">×</button>
                                </div>
                                <div style="
                                    padding: 24px;
                                    overflow-y: auto;
                                    max-height: calc(80vh - 120px);
                                ">
                                    <div id="tutorial-content"></div>
                                </div>
                                <div style="
                                    padding: 12px 16px;
                                    border-top: 1px solid #f0f0f0;
                                    text-align: right;
                                ">
                                    <button id="ok-tutorial-button" style="
                                        padding: 8px 15px;
                                        background-color: #1890ff;
                                        color: white;
                                        border: none;
                                        border-radius: 4px;
                                        cursor: pointer;
                                    ">我知道了</button>
                                </div>
                            </div>
                        </div>
                    `;

                    // 添加动画样式
                    const style = document.createElement('style');
                    style.textContent = `
                        @keyframes fadeIn {
                            from { opacity: 0; }
                            to { opacity: 1; }
                        }
                        @keyframes slideDown {
                            from { transform: translateY(-20px); opacity: 0; }
                            to { transform: translateY(0); opacity: 1; }
                        }
                        #custom-tutorial-modal h3 {
                            margin-top: 20px;
                            margin-bottom: 10px;
                            font-weight: 500;
                            color: #333;
                        }
                        #custom-tutorial-modal ul, #custom-tutorial-modal ol {
                            padding-left: 20px;
                            margin-bottom: 16px;
                        }
                        #custom-tutorial-modal li {
                            margin-bottom: 8px;
                        }
                        #custom-tutorial-modal strong {
                            font-weight: 600;
                            color: #1890ff;
                        }
                        #ok-tutorial-button:hover {
                            background-color: #40a9ff;
                        }
                        #close-tutorial-button:hover {
                            color: #333;
                        }
                    `;
                    document.head.appendChild(style);

                    // 添加模态框到DOM
                    document.body.insertAdjacentHTML('beforeend', modalHTML);

                    // 获取内容容器
                    const contentContainer = document.getElementById('tutorial-content');
                    if (!contentContainer) {
                        throw new Error('教程内容容器不存在');
                    }

                    // 填充教程内容
                    const tutorialHTML = `
                        <h3>基本功能</h3>
                        <ul>
                            <li><strong>自动学习:</strong>点击"自动学习"按钮,脚本会自动完成视频观看和文档阅读,不需手动操作。再次点击可暂停学习。</li>
                            <li><strong>清除进度:</strong>清除已保存的学习进度,重新开始学习。</li>
                            <li><strong>更多功能:</strong>点击后弹出菜单,包含自动答题、秒过视频、导出题库、清除日志、使用教程和答题设置等功能。</li>
                            <li><strong>自动答题:</strong>在答题页面自动填写答案(需要先获取题库)。系统会自动识别题目并填入正确答案。</li>
                            <li><strong>秒过视频:</strong>立即完成当前视频学习,标记为已完成。适用于不想等待视频播放完成的情况。</li>
                            <li><strong>导出题库:</strong>将已获取的答案导出为Excel文件,方便离线查看。文件会按章节和讲次命名,题目按序号排序。</li>
                            <li><strong>清除日志:</strong>清空运行日志面板,保持界面整洁。</li>
                            <li><strong>答题设置:</strong>设置是否自动提交答案和是否自动进入考试。可以根据个人需求自定义答题行为。</li>
                        </ul>

                        <h3>视频静音功能</h3>
                        <ul>
                            <li><strong>全局自动静音:</strong>脚本在启动时自动为所有视频静音,包括HTML5视频和JWPlayer播放器。</li>
                            <li><strong>兼容多种播放器:</strong>支持HTML5标准视频元素和特定课程使用的JWPlayer播放器。</li>
                            <li><strong>静音监控:</strong>脚本会持续监控页面变化,对新加载的视频自动应用静音。</li>
                            <li><strong>播放完成跳转:</strong>视频播放完成后会自动切换到下一个学习内容,全程无声音打扰。</li>
                        </ul>

                        <h3>使用步骤</h3>
                        <ol>
                            <li>登录(不可用)智慧校园平台后,脚本会自动加载并在页面右上角显示助手窗口。</li>
                            <li>首次使用时需要输入验证密钥完成验证(密钥有效期为2天)。</li>
                            <li>进入课程学习页面,点击【自动学习】开始自动完成视频观看和文档阅读任务。</li>
                            <li>如需暂停学习,再次点击【自动学习】按钮(此时按钮显示为【停止学习】)。</li>
                            <li>进入答题页面时,系统会自动获取答案并显示在答案列表中,点击顶部的【答案列表】标签可查看。</li>
                            <li>可以点击【更多功能】→【自动答题】自动填写答案,也可以手动查看答案进行填写。</li>
                            <li>完成答题后,可以点击【更多功能】→【导出题库】将答案保存为Excel文件,便于复习。</li>
                        </ol>

                        <h3>特别提示</h3>
                        <ul>
                            <li>验证密钥有效期默认为2天,到期后需重新验证。验证剩余时间显示在助手窗口标题栏右侧。</li>
                            <li>自动学习功能会保存进度,关闭页面后下次访问可以继续上次的学习进度。</li>
                            <li>为避免被系统检测,视频播放和文档阅读会模拟正常的学习行为,会有一定等待时间。</li>
                            <li>所有视频都会自动静音,避免多个视频同时播放造成声音干扰,可以安静学习。</li>
                            <li>导出的Excel文件会按题目序号自动排序,文件名包含章节和讲次信息,便于查找。</li>
                            <li>支持拖动插件窗口到合适位置,点击标题栏右侧的最小化按钮可隐藏插件,需要时再点击图标展开。</li>
                            <li>如果脚本运行不正常,请尝试刷新页面或重新安装最新版本的脚本。</li>
                        </ul>

                        <h3>界面说明</h3>
                        <ul>
                            <li><strong>运行日志:</strong>显示脚本执行过程中的操作记录和状态信息,帮助了解当前执行情况。</li>
                            <li><strong>答案列表:</strong>显示当前页面检测到的所有题目及答案,按序号排列,可直接查看正确答案。</li>
                            <li><strong>最小化按钮:</strong>点击标题栏右侧的按钮可以最小化助手窗口,再次点击可展开。</li>
                            <li><strong>更多功能菜单:</strong>点击【更多功能】按钮,展开包含自动答题、秒过视频等功能的下拉菜单。</li>
                        </ul>

                        <h3>快捷键</h3>
                        <ul>
                            <li><strong>Alt+A:</strong>自动答题 - 快速为当前页面的所有题目填写答案</li>
                            <li><strong>Alt+V:</strong>秒过视频 - 立即完成当前正在观看的视频</li>
                            <li><strong>Alt+L:</strong>开始/停止自动学习 - 切换自动学习状态</li>
                            <li><strong>Alt+E:</strong>导出题库 - 将答案导出为Excel文件</li>
                            <li><strong>Alt+H:</strong>显示/隐藏插件窗口 - 切换助手窗口的显示状态</li>
                        </ul>
                    `;

                    contentContainer.innerHTML = tutorialHTML;

                    // 添加ESC键关闭功能
                    function handleEscKey(e) {
                        if (e.key === 'Escape') {
                            closeModal();
                        }
                    }
                    document.addEventListener('keydown', handleEscKey);

                    // 添加关闭和确认按钮事件
                    function closeModal() {
                        const modal = document.getElementById('custom-tutorial-modal');
                        if (modal) {
                            modal.style.opacity = '0';
                            modal.style.transition = 'opacity 0.3s';
                            setTimeout(() => {
                                if (modal && modal.parentNode) {
                                    modal.parentNode.removeChild(modal);
                                }
                                // 移除样式以避免污染页面
                                if (style && style.parentNode) {
                                    style.parentNode.removeChild(style);
                                }
                            }, 300);
                        }
                        document.removeEventListener('keydown', handleEscKey);
                    }

                    // 绑定关闭按钮事件
                    const closeButton = document.getElementById('close-tutorial-button');
                    if (closeButton) {
                        closeButton.addEventListener('click', closeModal);
                    }

                    const okButton = document.getElementById('ok-tutorial-button');
                    if (okButton) {
                        okButton.addEventListener('click', closeModal);
                    }

                    // 点击背景关闭模态框
                    const modal = document.getElementById('custom-tutorial-modal');
                    if (modal) {
                        modal.addEventListener('click', function(e) {
                            if (e.target === this) {
                                closeModal();
                            }
                        });
                    }

                    // 记录日志
                    log('显示使用教程');

                } catch (error) {
                    console.error('打开教程模态框出错:', error);
                    alert('打开使用教程失败,请刷新页面后重试。\n错误信息: ' + error.message);
                }
            },
            // 优化拖动处理
            initDragEvents() {
                const box = document.querySelector('.rlBox');
                const dragZone = document.querySelector('.ant-card-head');
                let startX, startY, initialMouseX, initialMouseY;

                dragZone.addEventListener('mousedown', (e) => {
                    if (this.close) return; // 小化时禁止拖动
                    e.preventDefault();
                    this.isDragging = true;

                    const rect = box.getBoundingClientRect();
                    startX = rect.left;
                    startY = rect.top;
                    initialMouseX = e.clientX;
                    initialMouseY = e.clientY;

                    box.style.transition = 'none';
                    document.body.style.userSelect = 'none';
                });

                document.addEventListener('mousemove', (e) => {
                    if (!this.isDragging) return;

                    const dx = e.clientX - initialMouseX;
                    const dy = e.clientY - initialMouseY;

                    let newX = startX + dx;
                    let newY = startY + dy;

                    box.style.left = `${newX}px`;
                    box.style.top = `${newY}px`;
                    box.style.right = 'auto';

                    // 实时检查位置
                    this.checkPosition();
                });

                document.addEventListener('mouseup', () => {
                    if (this.isDragging) {
                        this.isDragging = false;
                        box.style.transition = 'all 0.2s';
                        document.body.style.userSelect = '';
                    }
                });

                // 添加摸支持
                dragZone.addEventListener('touchstart', (e) => {
                    const touch = e.touches[0];
                    const rect = box.getBoundingClientRect();
                    startX = rect.left;
                    startY = rect.top;
                    initialMouseX = touch.clientX;
                    initialMouseY = touch.clientY;
                    this.isDragging = true;
                });

                document.addEventListener('touchmove', (e) => {
                    if (!this.isDragging) return;
                    e.preventDefault();

                    const touch = e.touches[0];
                    const dx = touch.clientX - initialMouseX;
                    const dy = touch.clientY - initialMouseY;

                    let newX = startX + dx;
                    let newY = startY + dy;

                    const maxX = window.innerWidth - box.offsetWidth;
                    const maxY = window.innerHeight - box.offsetHeight;

                    newX = Math.min(Math.max(0, newX), maxX);
                    newY = Math.min(Math.max(0, newY), maxY);

                    box.style.left = `${newX}px`;
                    box.style.top = `${newY}px`;
                });

                document.addEventListener('touchend', () => {
                    this.isDragging = false;
                });
            },
            // 添加新方法
            saveLearningProgress() {
                try {
                    const currentChapter = document.querySelector('.nav-text.current');
                    const currentContent = document.querySelector('.tab-active .tab-inner');

                    if (currentChapter && this.autoLearning) {
                        // 获取当前页面URL和章节信息
                        const currentUrl = window.location.href;
                        const unitId = currentChapter.getAttribute('unitid');
                        const chapterName = currentChapter.querySelector('.node-text')?.textContent.trim() || '未知章节';

                        const progress = {
                            isLearning: this.autoLearning,
                            currentChapter: unitId,
                            currentContent: currentContent ? currentContent.getAttribute('itemid') : null,
                            currentContentName: currentContent ? currentContent.getAttribute('itemname') : null,
                            timestamp: Date.now(),
                            chapterName: chapterName,
                            currentUrl: currentUrl,
                            isPageSwitching: false
                        };

                        localStorage.setItem('learningProgress', JSON.stringify(progress));
                        setting.learningProgress = progress;

                        log(`学习进度已保存: ${chapterName}`);
                    }
                } catch (error) {
                    console.log('保存学习进度时出错:', error);
                }
            },
            checkLearningProgress() {
                try {
                    const savedProgress = localStorage.getItem('learningProgress');
                    if (savedProgress) {
                        const progress = JSON.parse(savedProgress);
                        const timeDiff = Date.now() - progress.timestamp;

                        // 如果保存时间在30分钟内且正在学习
                        if (timeDiff < 30 * 60 * 1000 && progress.isLearning) {
                            setting.learningProgress = progress;
                            log('检测到未完成的学习进度,准备恢复...');

                            // 设置自动学习状态
                            this.autoLearning = true;

                            // 等待页面完全加载
                            const waitForLoad = () => {
                                // 检查必要的DOM元素是否存在
                                const currentChapter = document.querySelector('.nav-text.current');
                                const tabInner = document.querySelector('.tab-inner');

                                if (!currentChapter || !tabInner) {
                                    log('等待页面加载...');
                                    setTimeout(waitForLoad, 1000);
                                    return;
                                }

                                // 获取当前章节信息
                                const chapterName = currentChapter.querySelector('.node-text')?.textContent.trim();
                                log(`恢复学习章节: ${chapterName || '未知章节'}`);

                                // 确保子章节列表展开
                                const subNav = currentChapter.closest('.nav-item.sup-item').querySelector('.sub-nav');
                                if (subNav) {
                                    subNav.style.display = 'block';
                                }

                                // 获取第一个内容标签
                                const firstTab = document.querySelector('.tab-inner');
                                if (firstTab) {
                                    log(`开始学习: ${firstTab.getAttribute('itemname')}`);
                                    firstTab.click();

                                    // 延迟启动学习
                                    setTimeout(() => {
                                        if (this.autoLearning) {
                                            log('开始自动学习...');
                                            this.processCurrentContent();
                                        }
                                    }, 1500);
                                } else {
                                    log('未找到可学习的内容,请刷新页面重试');
                                }
                            };

                            // 开始等待加载
                            setTimeout(waitForLoad, 2000);
                        } else {
                            localStorage.removeItem('learningProgress');
                        }
                    }
                } catch (error) {
                    console.error('检查学习进度时出错:', error);
                    log('恢复进度失败,请刷新页面重试');
                }
            },
            restoreLearningProgress() {
                try {
                    const progress = setting.learningProgress;
                    if (!progress || !progress.isLearning) return;

                    // 查找并点击对应章节
                    const chapterLink = document.querySelector(`.nav-text[unitid="${progress.currentChapter}"]`);
                    if (chapterLink) {
                        log('正在恢复上次的学习进度...');
                        chapterLink.click();

                        // 等待章节展开后点击对应内容
                        setTimeout(() => {
                            const contentLink = document.querySelector(`.tab-inner[itemid="${progress.currentContent}"]`);
                            if (contentLink) {
                                contentLink.click();

                                // 恢复自动学习状态
                                setTimeout(() => {
                                    this.autoLearning = true;
                                    this.processCurrentContent();
                                    log('学习进度已恢复,继续学习');
                                }, 1500);
                            }
                        }, 1000);
                    }
                } catch (error) {
                    console.log('恢复学习进度时出错:', error);
                }
            },
            // 添加清除进度方法
            clearProgress() {
                try {
                    localStorage.removeItem('learningProgress');
                    this.autoLearning = false;
                    log("已清除学习进度");
                    this.$message.success("学习进度已清除");
                } catch (error) {
                    log("清除进度失败: " + error.message);
                    this.$message.error("清除进度失败");
                }
            },
            // 新增方法:开始学习新章节
            startLearningNewChapter(chapter, chapterName) {
                const startLearning = () => {
                    const subNav = chapter.querySelector('.sub-nav');
                    if (!subNav) {
                        throw new Error("未找到子章节列表");
                    }

                    subNav.style.display = 'block';

                    // 获取第一个子章节
                    const firstSubChapter = subNav.querySelector('.sub-nav-text');
                    if (!firstSubChapter) {
                        throw new Error("未找到子章节");
                    }

                    log(`点击第一个子章节...`);
                    firstSubChapter.click();

                    // 等待子章节内容加载
                    setTimeout(() => {
                        // 获取并点击第一个内容标签
                        const tabList = document.querySelectorAll('.tab-inner');
                        if (!tabList || tabList.length === 0) {
                            throw new Error("未找到可学习的内容");
                        }

                        const firstTab = tabList[0];
                        log(`开始学习: ${firstTab.getAttribute('itemname')}`);
                        firstTab.click();

                        // 确保内容加载完成后开始学习
                        setTimeout(() => {
                            if (this.autoLearning) {
                                log(`开始自动学习新章节内容...`);
                                this.processCurrentContent();
                            }
                        }, 1500);
                    }, 1000);
                };

                // 重试机制
                let retryCount = 0;
                const maxRetries = 3;

                const tryStartLearning = () => {
                    try {
                        startLearning();
                    } catch (error) {
                        retryCount++;
                        if (retryCount < maxRetries) {
                            log(`启动学习失败,${maxRetries - retryCount}秒后重试...`);
                            setTimeout(tryStartLearning, 1000);
                        } else {
                            this.autoLearning = false;
                            log(`无法启动学习: ${error.message}`);
                            this.$message.error("无法启动学习,请手动点击内容或刷新页面");
                        }
                    }
                };

                // 延迟启动,确保DOM已更新
                setTimeout(tryStartLearning, 1000);
            },
            // 添加URL变化监听器
            initUrlChangeListener() {
                // 监听 popstate 事件
                window.addEventListener('popstate', () => {
                    this.handleUrlChange();
                });

                // 重写 pushState 和 replaceState 方法以捕获URL变化
                const originalPushState = window.history.pushState;
                const originalReplaceState = window.history.replaceState;

                window.history.pushState = function() {
                    originalPushState.apply(this, arguments);
                    window.vue.handleUrlChange();
                };

                window.history.replaceState = function() {
                    originalReplaceState.apply(this, arguments);
                    window.vue.handleUrlChange();
                };
            },

            // 处理URL变化
            handleUrlChange() {
                // 检查是否是章节页面
                if (location.pathname.includes('/study/unit/')) {
                    // 获取当前章节ID
                    const currentUnitId = location.pathname.match(/\/unit\/(\d+)/)?.[1];
                    if (currentUnitId) {
                        // 检查是否有保存的进度
                        const savedProgress = localStorage.getItem('learningProgress');
                        if (savedProgress) {
                            const progress = JSON.parse(savedProgress);

                            // 如果标记为页面正在切换状态,无论章节ID是否一致,都重新启动学习
                            if (progress.isLearning) {
                                if (progress.isPageSwitching || progress.currentChapter === currentUnitId) {
                                    log('检测到章节切换或URL变化,准备继续学习...');

                                    // 如果是切换页面状态,先更新进度状态,取消切换标记
                                    if (progress.isPageSwitching) {
                                        progress.isPageSwitching = false;
                                        progress.currentChapter = currentUnitId;
                                        localStorage.setItem('learningProgress', JSON.stringify(progress));
                                        setting.learningProgress = progress;
                                    }

                                    // 设置自动学习状态并启动学习
                                    this.autoLearning = true;
                                    setTimeout(() => {
                                        this.startLearningCurrentChapter();
                                    }, 2000); // 等待页面完全加载
                                }
                            }
                        }
                    }
                }
            },

            // 开始学习当前章节
            startLearningCurrentChapter() {
                try {
                    // 检查页面是否已加载完成
                    if (document.readyState !== 'complete') {
                        log("页面正在加载中,等待页面加载完成...");
                        setTimeout(() => {
                            if (this.autoLearning) {
                                this.startLearningCurrentChapter();
                            }
                        }, 1000);
                        return;
                    }

                    // 获取当前章节
                    const currentChapter = document.querySelector('.nav-text.current')?.closest('.nav-item.sup-item');
                    if (!currentChapter) {
                        log("未找到当前章节,等待DOM加载...");
                        setTimeout(() => {
                            if (this.autoLearning) {
                                this.startLearningCurrentChapter();
                            }
                        }, 2000);
                        return;
                    }

                    const chapterName = currentChapter.querySelector('.node-text')?.textContent.trim();
                    log(`准备学习章节: ${chapterName || '未知章节'}`);

                    // 展开子章节列表并开始学习
                    setTimeout(() => {
                        this.startLearningNewChapter(currentChapter, chapterName);
                    }, 1000); // 额外等待1秒确保DOM状态稳定
                } catch (error) {
                    log(`启动学习失败: ${error.message}`);
                    // 延迟重试
                    setTimeout(() => {
                        if (this.autoLearning) {
                            this.startLearningCurrentChapter();
                        }
                    }, 2000);
                }
            },
        }
    });
}

// 自动阅读文档功能
function autoReadDocument() {
    // 获取当前文档总页数
    const totalPages = parseInt(document.querySelector('.flexpaper_lblTotalPages')?.textContent.replace('/ ', '')) || 0;

    if(totalPages === 0) {
        log("未检测到文档页数,请确保文档已加载");
        return;
    }

    // 计算阅读时间和翻页间隔
    let totalReadingTime, pageInterval;

    if(totalPages < 10) {
        // 小于10页文档,使用固定1秒1页的速度
        totalReadingTime = totalPages;
        pageInterval = 1000; // 1秒1页
    } else if(totalPages > 50) {
        // 超过50页文档,固定30秒完成
        totalReadingTime = 30;
        pageInterval = Math.max(totalReadingTime / totalPages * 1000, 300); // 每页间隔时间(毫秒),最小300ms
    } else {
        // 10-50页文档使用原有逻辑
        totalReadingTime = totalPages > 20 ? 20 : 10; // 超过20页固定20秒,否则10秒
        pageInterval = Math.max(totalReadingTime / totalPages * 1000, 300); // 每页间隔时间(毫秒),最小300ms
    }

    log(`开始自动阅读文档,共${totalPages}页,预计用时${totalReadingTime}秒,翻页间隔${Math.round(pageInterval)}毫秒`);

    let currentPage = 1;
    const readInterval = setInterval(() => {
        if(currentPage > totalPages) {
            clearInterval(readInterval);
            log("文档阅读完成,准备切换到下一个内容");
            switchToNextContent();
            return;
        }

        // 模拟翻页
        const nextButton = document.querySelector('.flexpaper_bttnPrevNext');
        if(nextButton) {
            nextButton.click();
            log(`正在阅读第${currentPage}页,共${totalPages}页`);
            currentPage++;
        }
    }, pageInterval); // 使用计算出的翻页间隔
}

// 切换到下一个内容
function switchToNextContent() {
    // 获取所有标签页
    const tabs = document.querySelectorAll('.tab-inner');
    let currentTabIndex = -1;

    // 找到当前激活的标签页
    tabs.forEach((tab, index) => {
        if(tab.parentElement.classList.contains('tab-active')) {
            currentTabIndex = index;
        }
    });

    // 如果还有下一个标签页,则切换
    if(currentTabIndex < tabs.length - 1) {
        const nextTab = tabs[currentTabIndex + 1];
        log(`切换到下一个内容: ${nextTab.getAttribute('itemname')}`);

        // 根据内容类型执行不同操作
        const itemType = nextTab.getAttribute('itemtype');
        nextTab.click();

                        setTimeout(() => {
            if(itemType === '10') { // 视频类型
                passVideo();
            } else if(itemType === '20') { // 文档类型
                autoReadDocument();
            }
        }, 1500);
    } else {
        log("已完成所有内容学习");
    }
}

// 初始化获取答案,延迟5秒防止流程崩溃
function initGetAnswer(settings){
    var url = location.origin + settings.url;
    var data = settings.data.replace(/(testPaperId=).*?(&)/,'$1' + '1250' + '$2');
    console.log("=====")
    console.log(url,'url')
    console.log(data)
    getAnswer(url,data);
}

// 添加答案检查函数
function checkAnswers() {
    return new Promise((resolve) => {
        let checkCount = 0;
        const maxChecks = 30; // 最多等待30秒

        function check() {
            if (setting.datas && setting.datas.length > 0) {
                log("答案已获取完成,开始答题...");
                resolve(true);
            } else if (checkCount >= maxChecks) {
                log("等待答案超时,请确保答案已正确获取");
                resolve(false);
            } else {
                checkCount++;
                log(`等待答案获取中...(${checkCount}/${maxChecks})`);
                setTimeout(check, 1000);
            }
        }

        check();
    });
}

// 添加答案查找函数
function findAnswerForQuestion(questionText) {
    if (!setting.datas || setting.datas.length === 0) {
        return null;
    }

    // 清理题目文本
    const cleanedQuestionText = cleanHtmlTags(questionText).trim();

    // 在答案列表中查找匹配的题目
    for (const answerData of setting.datas) {
        const cleanedAnswerQuestion = cleanHtmlTags(answerData.question).trim();

        // 检查题目是否匹配
        if (cleanedQuestionText.includes(cleanedAnswerQuestion) ||
            cleanedAnswerQuestion.includes(cleanedQuestionText)) {
            return answerData.answer;
        }
    }

    return null;
}

// 修改自动答题函数
async function autoAnswerQuestions() {
    log("准备自动答题...");

  // 获取所有题目
  const questions = document.querySelectorAll('.view-test');
  if(!questions || questions.length === 0) {
        log("未找到题目,请确认是否在答题页面");
                    return;
                }

  log(`共发现 ${questions.length} 道题目`);
    let answeredCount = 0;

    // 遍历每个题目
    for (let index = 0; index < questions.length; index++) {
        const question = questions[index];
        try {
    // 获取题目类型
    const isMultiChoice = question.querySelector('.t-option .input-c') !== null; // 多选
    const isSingleChoice = question.querySelector('.t-option .input-r') !== null; // 单选
            const isFillBlank = question.querySelector('.fillblank') !== null; // 填空

            // 获取题目文本
            const questionText = question.querySelector('.test-text-tutami')?.textContent.trim();
            if(!questionText) {
                log(`第 ${index + 1} 题未找到题目文本`);
                continue;
            }

            // 查找答案
            const answer = findAnswerForQuestion(questionText);
            if(!answer) {
                log(`第 ${index + 1} 题未找到匹配的答案`);
                continue;
            }

            log(`正在答第 ${index + 1} 题...`);

            // 根据题型填写答案
    if(isMultiChoice) {
                // 处理多选题
                const answerLetters = answer.split('\n').map(a => a.trim().charAt(0));
        const options = question.querySelectorAll('.t-option');
        options.forEach((option, idx) => {
                    const letter = String.fromCharCode(65 + idx);
                    if(answerLetters.includes(letter)) {
            const checkbox = option.querySelector('.input-c');
            if(checkbox && !checkbox.classList.contains('selected')) {
              checkbox.click();
                            log(`  - 选择了选项 ${letter}`);
            }
          }
        });
                answeredCount++;
    } else if(isSingleChoice) {
                // 处理单选题
                const answerLetter = answer.trim().charAt(0);
      const options = question.querySelectorAll('.t-option');
      options.forEach((option, idx) => {
                    const letter = String.fromCharCode(65 + idx);
                    if(letter === answerLetter) {
          const radio = option.querySelector('.input-r');
          if(radio && !radio.classList.contains('selected')) {
            radio.click();
                            log(`  - 选择了选项 ${letter}`);
          }
        }
      });
                answeredCount++;
    } else if(isFillBlank) {
                // 处理填空题
                const input = question.querySelector('.fillblank');
      if(input) {
                    const fillAnswer = answer.replace(/^.*?\./, '').trim();
                    input.value = fillAnswer;
                    input.dispatchEvent(new Event('input', { bubbles: true }));
                    input.dispatchEvent(new Event('change', { bubbles: true }));
                    log(`  - 填写答案: ${fillAnswer}`);
                    answeredCount++;
                }
            }
        } catch(error) {
            log(`第 ${index + 1} 题答题出错: ${error.message}`);
        }
    }

    log(`自动答题完成!成功答题 ${answeredCount} 道题目`);

    // 如果启用了自动提交
    if(setting.autoSubmit) {
        const submitBtn = document.querySelector('#submit_exam');
        if(submitBtn) {
            log("准备自动提交答案...");
                        setTimeout(() => {
                submitBtn.click();

                // 监听确认对话框并自动点击"坚持提交"
                log("等待确认对话框...");
                const checkConfirmDialog = setInterval(() => {
                    const confirmBtn = document.querySelector('.d-button.d-state-highlight[value="坚持提交"]');
                    if(confirmBtn) {
                        clearInterval(checkConfirmDialog);
                        log("检测到确认对话框,自动点击'坚持提交'");
                            setTimeout(() => {
                            confirmBtn.click();

                            // 监听页面变化,等待返回测验列表页
                            log("等待返回测验列表页...");
                            setTimeout(() => {
                                if(window.vue && window.vue.autoLearning) {
                                    log("检测自动学习状态,准备继续下一内容...");
                                    setTimeout(() => {
                                        // 尝试获取页面类型
                                        const pageType = checkPageType();
                                        // 如果已经回到测验页面,继续学习
                                        if(pageType === 'quiz') {
                                            window.vue.switchToNextContent();
                                        }
                                    }, 2000);
                                }
                            }, 3000);
                        }, 500);
                    }
                }, 500);

                // 5秒后清除定时器,避免无限循环
                setTimeout(() => {
                    clearInterval(checkConfirmDialog);
                }, 5000);
            }, 1000);
        } else {
            log("未找到提交按钮,请手动提交");
        }
    } else {
        if(window.vue) {
            window.vue.$message.info('答题完成,请检查后手动提交');
        }
    }
}

// 添加自动答题按钮
function addAutoAnswerButton() {
  const btnArea = document.querySelector('.practice-action');
  if(!btnArea) return;

  const btn = document.createElement('a');
  btn.innerText = '自动答题';
  btn.className = 'btn-public btn-min';
  btn.href = 'javascript:void(0)';
  btn.onclick = autoAnswerQuestions;

  btnArea.appendChild(btn);
  log("已添加自动答题按钮");
}

// 初始化
function initAutoAnswer() {
  if(location.href.includes('/examSubmit/')) {
    log("检测到答题页面");
    setTimeout(addAutoAnswerButton, 2000);
  }
}

initAutoAnswer();

// 脚本入口
initView();
//监听跳过视频按钮
$('#rl_passVideo').click(function(){passVideo();});
//监听url访问,当访问了加载题目的url时,将获取答案
$(document).ready(function(){
    $(document).ajaxComplete(function (evt, request, settings) {
        if(settings.url.search('getExamPaper') != -1){
            setting.logs.unshift("您已打开作业界面,5秒后将为您获取答案")
            setTimeout(initGetAnswer,5000, settings);
        }
    });
})

// 获取验证时间的函数
function getValidTime() {
    try {
        const data = localStorage.getItem('scriptValidUntil');
        if (!data) return null;

        const { time, hash } = JSON.parse(data);
        if (!time || !hash) return null;

        // 验证哈希值
        if (hash !== CryptoJS.SHA256(time.toString()).toString()) {
            localStorage.removeItem('scriptValidUntil');
            return null;
        }

        return time;
    } catch (e) {
        console.error('获取验证时间出错:', e);
        localStorage.removeItem('scriptValidUntil');
        return null;
    }
}

// 在界面中添加自动学习按钮
function addAutoLearnButton() {
    const buttonGroup = document.querySelector('.ant-btn-group');
    if(!buttonGroup) return;

    const autoLearnBtn = document.createElement('button');
    autoLearnBtn.className = 'ant-btn ant-btn-primary';
    autoLearnBtn.style.width = '25%';
    autoLearnBtn.innerHTML = '<span>自动学习</span>';
    autoLearnBtn.onclick = () => window.vue.startAutoLearning();

    buttonGroup.appendChild(autoLearnBtn);
}

// 添加自动答题相关功能
function initAutoExam() {
    // 先检查页面类型
    const pageType = checkPageType();

    // 如果不是测验页面,直接返回
    if(pageType !== 'quiz') {
        return;
    }

    log("检测到测验页面,初始化答题功能...");

    // 添加配置按钮到界面
    const configBtn = document.createElement('button');
    configBtn.className = 'ant-btn ant-btn-primary';
    configBtn.innerHTML = `
        <span>答题设置</span>
    `;
    configBtn.onclick = showExamConfig;

    // 找到按钮区域并添加配置按钮
    const btnArea = document.querySelector('.ant-btn-group');
    if(btnArea) {
        btnArea.appendChild(configBtn);
        log("已添加答题设置按钮");
    }

    // 自动处理测验
    handleQuiz();
}

// 显示答题配置对话框
function showExamConfig() {
    const configHtml = `
        <div class="exam-config" style="padding: 20px;">
            <h3>答题设置</h3>
            <div style="margin: 10px 0;">
                <label>
                    <input type="checkbox" ${setting.autoSubmit ? 'checked' : ''} id="autoSubmit">
                    自动提交答案
                </label>
            </div>
            <div style="margin: 10px 0;">
                <label>
                    <input type="checkbox" ${setting.autoEnterExam ? 'checked' : ''} id="autoEnterExam">
                    自动进入考试
                </label>
            </div>
            <div style="margin-top: 20px;">
                <button class="ant-btn ant-btn-primary" onclick="saveExamConfig()">保存设置</button>
            </div>
                    </div>
                `;

    // 使用 ant-design-vue 的对话框显示配置
    if(window.vue) {
        window.vue.$info({
            title: '答题设置',
            content: configHtml,
            width: 400
        });
    }
}

// 保存答题配置
window.saveExamConfig = function() {
    setting.autoSubmit = document.getElementById('autoSubmit').checked;
    setting.autoEnterExam = document.getElementById('autoEnterExam').checked;

    // 保存到localStorage
    localStorage.setItem('examConfig', JSON.stringify({
        autoSubmit: setting.autoSubmit,
        autoEnterExam: setting.autoEnterExam
    }));

    if(window.vue) {
        window.vue.$message.success('设置已保存');
    }
}

// 加载保存的配置
function loadExamConfig() {
    try {
        const savedConfig = localStorage.getItem('examConfig');
        if(savedConfig) {
            const config = JSON.parse(savedConfig);
            // 使用默认值作为后备
            setting.autoSubmit = config.autoSubmit !== undefined ? config.autoSubmit : false;
            setting.autoEnterExam = config.autoEnterExam !== undefined ? config.autoEnterExam : true;
            log("已加载答题设置");
        } else {
            // 如果没有保存的配置,设置默认值
            setting.autoSubmit = false;
            setting.autoEnterExam = true;

            // 保存默认设置
                        localStorage.setItem('examConfig', JSON.stringify({
                autoSubmit: false,
                autoEnterExam: true
            }));
            log("已设置默认答题选项");
        }
    } catch(e) {
        console.error('加载答题配置失败:', e);
        // 出错时使用默认值
        setting.autoSubmit = false;
        setting.autoEnterExam = true;
    }
}

// 修改自动答题函数
function autoAnswerQuestions() {
    log("开始自动答题...");

    // 获取所有题目
    const questions = document.querySelectorAll('.view-test');
    if(!questions || questions.length === 0) {
        log("未找到题目,请确认是否在答题页面");
        return;
    }

    log(`共发现 ${questions.length} 道题目`);
    let answeredCount = 0;

    questions.forEach((question, index) => {
        try {
            // 获取题目类型
            const isMultiChoice = question.querySelector('.t-option .input-c') !== null; // 多选
            const isSingleChoice = question.querySelector('.t-option .input-r') !== null; // 单选
            const isFillBlank = question.querySelector('.fillblank') !== null; // 填空

            // 获取题目文本用于匹配答案
            const questionText = question.querySelector('.test-text-tutami')?.textContent.trim();
            if(!questionText) {
                log(`第 ${index + 1} 题未找到题目文本`);
                return;
            }

            // 在答案列表中查找匹配的答案
            const answer = findAnswerForQuestion(questionText);
            if(!answer) {
                log(`第 ${index + 1} 题未找到匹配的答案`);
                return;
            }

            // 根据题型填写答案
            if(isMultiChoice) {
                // 处理多选题
                const answerLetters = answer.split('\n').map(a => a.trim().charAt(0));
                const options = question.querySelectorAll('.t-option');
                options.forEach((option, idx) => {
                    const letter = String.fromCharCode(65 + idx);
                    if(answerLetters.includes(letter)) {
                        const checkbox = option.querySelector('.input-c');
                        if(checkbox && !checkbox.classList.contains('selected')) {
                            checkbox.click();
                        }
                    }
                });
                answeredCount++;
            } else if(isSingleChoice) {
                // 处理单选题
                const answerLetter = answer.trim().charAt(0);
                const options = question.querySelectorAll('.t-option');
                options.forEach((option, idx) => {
                    const letter = String.fromCharCode(65 + idx);
                    if(letter === answerLetter) {
                        const radio = option.querySelector('.input-r');
                        if(radio && !radio.classList.contains('selected')) {
                            radio.click();
                        }
                    }
                });
                answeredCount++;
            } else if(isFillBlank) {
                // 处理填空题
                const input = question.querySelector('.fillblank');
                if(input) {
                    input.value = answer.replace(/^.*?\./, '').trim();
                    // 触发input事件
                    input.dispatchEvent(new Event('input', { bubbles: true }));
                    input.dispatchEvent(new Event('change', { bubbles: true }));
                    answeredCount++;
                }
            }
        } catch(error) {
            log(`第 ${index + 1} 题答题出错: ${error.message}`);
        }
    });

    log(`自动答题完成!成功答题 ${answeredCount} 道题目`);

    // 如果启用了自动提交
    if(setting.autoSubmit) {
        const submitBtn = document.querySelector('#submit_exam');
        if(submitBtn) {
            log("准备自动提交答案...");
            setTimeout(() => {
                submitBtn.click();

                // 监听确认对话框并自动点击"坚持提交"
                log("等待确认对话框...");
                const checkConfirmDialog = setInterval(() => {
                    const confirmBtn = document.querySelector('.d-button.d-state-highlight[value="坚持提交"]');
                    if(confirmBtn) {
                        clearInterval(checkConfirmDialog);
                        log("检测到确认对话框,自动点击'坚持提交'");
                        setTimeout(() => {
                            confirmBtn.click();

                            // 监听页面变化,等待返回测验列表页
                            log("等待返回测验列表页...");
                            setTimeout(() => {
                                if(window.vue && window.vue.autoLearning) {
                                    log("检测自动学习状态,准备继续下一内容...");
                                    setTimeout(() => {
                                        // 尝试获取页面类型
                                        const pageType = checkPageType();
                                        // 如果已经回到测验页面,继续学习
                                        if(pageType === 'quiz') {
                                            window.vue.switchToNextContent();
                                        }
                                    }, 2000);
                                }
                            }, 3000);
                        }, 500);
                    }
                }, 500);

                // 5秒后清除定时器,避免无限循环
                setTimeout(() => {
                    clearInterval(checkConfirmDialog);
                }, 5000);
            }, 1000);
        } else {
            log("未找到提交按钮,请手动提交");
        }
    } else {
                        if(window.vue) {
            window.vue.$message.info('答题完成,请检查后手动提交');
        }
    }
}

// 在页面加载完成后初始化
document.addEventListener('DOMContentLoaded', () => {
    loadExamConfig();
    initAutoExam();
    initPageChangeListener();
});

// 修改页面类型识别逻辑
function checkPageType() {
    // 获取当前打开的标签页信息
    const activeTab = document.querySelector('.tab-active .tab-inner');
    if (!activeTab) {
        return null;
    }

    // 获取页面信息
    const itemType = activeTab.getAttribute('itemtype');
    const itemName = activeTab.getAttribute('itemname') || '';

    // 测验页面的多重判断条件
    const isQuiz = (
        // 1. 通过标题关键词判断
        itemName.includes('测试题') ||
        itemName.includes('测验题') ||
        itemName.includes('练习题') ||
        // 2. 通过页面元素判断
        document.querySelector('.h-commit-tip') !== null ||
        document.querySelector('.exam_submit_score') !== null ||
        document.querySelector('.enter_exam') !== null ||
        document.querySelector('.doObjExam') !== null ||
        // 3. 通过URL判断
        location.href.includes('/examSubmit/') ||
        // 4. 通过图标判断
        activeTab.querySelector('.icon-edit02') !== null ||
        // 5. 通过itemType判断
        itemType === '50' ||
        // 6. 通过页面结构判断
        document.querySelector('.h-result-table') !== null ||
        // 7. 通过提交次数信息判断
        document.querySelector('.h-commit-info') !== null ||
        // 8. 通过测验成绩表格判断(测验完成后的页面)
        document.querySelector('.exam-record-table') !== null
    );

    if (isQuiz) {
        // 检测是否为测验完成后的结果页面
        const isResultPage = (
            document.querySelector('.exam-record-table') !== null ||
            document.querySelector('.h-result-table') !== null ||
            (document.querySelector('.h-commit-tip') &&
             document.querySelector('.h-commit-tip').textContent.includes('已提交'))
        );

        if (isResultPage) {
            log("识别到测验结果页面,准备继续学习");
            // 如果是自动学习模式,则继续到下一内容
            if (window.vue && window.vue.autoLearning) {
                setTimeout(() => window.vue.switchToNextContent(), 1500);
            }
        }

        // 输出详细的识别信息
        log(`识别到测验页面:`);
        log(`- 标题: ${itemName}`);
        log(`- 类型: ${itemType}`);
        if (document.querySelector('.h-commit-tip')) {
            const submitInfo = document.querySelector('.h-commit-tip').textContent;
            log(`- 提交信息: ${submitInfo.trim()}`);
        }
        return 'quiz';
    }

    // 其他页面类型判断
    if (itemType === '10') {
        return 'video';
    } else if (itemType === '20') {
        return 'document';
    }

    return null;
}

// 修改handleQuiz函数中的答题逻辑
function handleQuiz() {
    log("检测到测验页面,准备处理...");

    // 检测是否是测验结果页面
    const isResultPage = (
        document.querySelector('.exam-record-table') !== null ||
        document.querySelector('.h-result-table') !== null ||
        (document.querySelector('.h-commit-tip') &&
         document.querySelector('.h-commit-tip').textContent.includes('已提交'))
    );

    if (isResultPage) {
        log("检测到测验已完成,准备继续下一个学习内容");
        if (window.vue && window.vue.autoLearning) {
            setTimeout(() => window.vue.switchToNextContent(), 1500);
        }
        return;
    }

    // 获取测验信息
    const quizInfo = {
        title: document.querySelector('.tab-active .tab-inner')?.getAttribute('itemname') || '未知测验',
        submitLimit: document.querySelector('.h-commit-info')?.textContent.match(/可提交次数:(\d+)次/) || ['', '未知'],
        timeLimit: document.querySelector('.h-commit-info')?.textContent.includes('不限时') ? '不限时' :
                  document.querySelector('.h-commit-info')?.textContent.match(/限时:(\d+)分钟/) || ['', '未知']
    };

    log(`测验信息:`);
    log(`- 标题: ${quizInfo.title}`);
    log(`- 提交次数限制: ${quizInfo.submitLimit[1]}次`);
    log(`- 时间限制: ${quizInfo.timeLimit === '不限时' ? '不限时' : quizInfo.timeLimit[1] + '分钟'}`);

    // 检查是否有"继续"按钮(未完成的测验)
    const enterBtn = document.querySelector('a.link-action.enter_exam');
    if(enterBtn) {
        const examId = enterBtn.id || '';
        log(`发现未完成的测验 (ID: ${examId}),准备继续答题...`);

        // 确保自动进入答题功能已启用
        if(setting.autoEnterExam) {
            log("自动进入答题已启用,即将进入答题页面...");

            // 模拟点击事件
            try {
                // 先尝试直接触发点击事件
                enterBtn.click();
                log("已触发进入答题页面");

                // 等待页面加载和答案获取
                waitForAnswersAndQuestions();

            } catch(error) {
                log(`进入答题页面时出错: ${error.message}`);
                log("请尝试手动点击'继续'按钮");
            }
        } else {
            log("自动进入答题已禁用,请手动点击'继续'按钮");
        }
        return;
    }

    // 检查是否已在答题页面
    const questions = document.querySelectorAll('.view-test');
    if(questions && questions.length > 0) {
        log(`已在答题页面,等待答案获取...`);
        waitForAnswersAndQuestions();
        return;
    }

    // 检查是否有开始答题按钮
    const startBtn = document.querySelector('.doObjExam');
    if(startBtn) {
        log("发现新测验,准备开始答题...");
        if(setting.autoEnterExam) {
            setTimeout(() => {
                startBtn.click();
                log("已自动开始答题");
                // 等待页面加载和答案获取
                waitForAnswersAndQuestions();
            }, 1000);
        } else {
            log("自动进入答题已禁用,请手动点击开始按钮");
        }
        return;
    }

    log("等待页面加载完成...");
}

// 修改等待答案和题目加载的函数
function waitForAnswersAndQuestions() {
    let checkCount = 0;
    const maxChecks = 30; // 最多等待30秒

    function check() {
        // 检查题目是否加载
        const questions = document.querySelectorAll('.view-test');
        if (!questions || questions.length === 0) {
            if (checkCount >= maxChecks) {
                log("等待题目加载超时,请刷新页面重试");
                return;
            }
            checkCount++;
            setTimeout(check, 1000);
            return;
        }

        // 检查答案是否已获取
        if (!setting.datas || setting.datas.length === 0) {
            if (checkCount >= maxChecks) {
                log("等待答案获取超时,请确保答案已正确获取");
                return;
            }
            checkCount++;
            setTimeout(check, 1000);
            return;
        }

        // 检查答案匹配情况
        checkAnswerMatching(questions).then(matchResult => {
            if (matchResult.success) {
                log("答案匹配检查完成:");
                log(`- 题目总数:${matchResult.totalQuestions}道`);
                log(`- 成功匹配:${matchResult.matchedCount}道`);
                if (matchResult.unmatchedQuestions.length > 0) {
                    log(`- 未匹配题目:${matchResult.unmatchedQuestions.join(', ')}题`);
                }

                if (matchResult.matchedCount > 0) {
                    // 开始自动答题
                    setTimeout(() => {
                        autoAnswerQuestions();
                    }, 1000);
                } else {
                    log("没有找到任何可匹配的答案,请检查答案是否正确");
                }
            } else {
                log("答案匹配检查失败,请刷新页面重试");
            }
        });
    }

    // 开始检查
    check();
}

// 添加答案匹配检查函数
async function checkAnswerMatching(questions) {
    try {
        const result = {
            success: true,
            totalQuestions: questions.length,
            matchedCount: 0,
            unmatchedQuestions: []
        };

        // 遍历所有题目进行检查
        for (let i = 0; i < questions.length; i++) {
            const question = questions[i];
            const questionText = question.querySelector('.test-text-tutami')?.textContent.trim();

            if (!questionText) {
                result.unmatchedQuestions.push(i + 1);
                continue;
            }

            // 清理题目文本
            const cleanedQuestionText = cleanHtmlTags(questionText).trim();
            let matched = false;

            // 在答案列表中查找匹配的题目
            for (const answerData of setting.datas) {
                const cleanedAnswerQuestion = cleanHtmlTags(answerData.question).trim();

                // 检查题目是否匹配
                if (cleanedQuestionText.includes(cleanedAnswerQuestion) ||
                    cleanedAnswerQuestion.includes(cleanedQuestionText)) {
                    result.matchedCount++;
                    matched = true;
                    break;
                }
            }

            if (!matched) {
                result.unmatchedQuestions.push(i + 1);
            }
        }

        return result;
                    } catch (error) {
        return {
            success: false,
            error: error.message
        };
    }
}

// 修改handleQuiz函数中的日志部分
function handleQuiz() {
    log("检测到测验页面,准备处理...");

    // 获取测验信息
    const quizInfo = {
        title: document.querySelector('.tab-active .tab-inner')?.getAttribute('itemname') || '未知测验',
        submitLimit: document.querySelector('.h-commit-info')?.textContent.match(/可提交次数:(\d+)次/) || ['', '未知'],
        timeLimit: document.querySelector('.h-commit-info')?.textContent.includes('不限时') ? '不限时' :
                  document.querySelector('.h-commit-info')?.textContent.match(/限时:(\d+)分钟/) || ['', '未知']
    };

    // 检查是否有"继续"按钮(未完成的测验)
    const enterBtn = document.querySelector('a.link-action.enter_exam');
    if(enterBtn) {
        const examId = enterBtn.id || '';
        log(`准备继续答题 (ID: ${examId})`);

        if(setting.autoEnterExam) {
            try {
                enterBtn.click();
                waitForAnswersAndQuestions();
            } catch(error) {
                log(`进入答题页面时出错: ${error.message}`);
                log("请尝试手动点击'继续'按钮");
            }
        } else {
            log("自动进入答题已禁用,请手动点击'继续'按钮");
        }
        return;
    }

    // 检查是否已在答题页面
    const questions = document.querySelectorAll('.view-test');
    if(questions && questions.length > 0) {
        waitForAnswersAndQuestions();
        return;
    }

    // 检查是否有开始答题按钮
    const startBtn = document.querySelector('.doObjExam');
    if(startBtn) {
        if(setting.autoEnterExam) {
            setTimeout(() => {
                startBtn.click();
                waitForAnswersAndQuestions();
            }, 1000);
        } else {
            log("自动进入答题已禁用,请手动点击开始按钮");
        }
        return;
    }
}

// 添加页面变化监听
function initPageChangeListener() {
    // 监听标签页切换
    const tabContainer = document.querySelector('.tabs');
    if(tabContainer) {
        const observer = new MutationObserver((mutations) => {
            mutations.forEach((mutation) => {
                if(mutation.type === 'attributes' && mutation.attributeName === 'class') {
                    const pageType = checkPageType();
                    if(pageType === 'quiz') {
                        log("检测到切换到测验页面");
                        handleQuiz();
                    }
                }
            });
        });

        observer.observe(tabContainer, {
            attributes: true,
            subtree: true,
            attributeFilter: ['class']
        });
    }
}

// 添加全局视频静音功能
function initGlobalMute() {
    log("初始化全局视频静音功能...");

    // 自动静音所有HTML5视频元素,处理已存在的视频
    function muteAllVideos() {
        const videos = document.getElementsByTagName('video');
        if (videos.length > 0) {
            for (let i = 0; i < videos.length; i++) {
                videos[i].muted = true;
                log(`已自动静音第${i+1}个HTML5视频`);
            }
        }

        // 尝试使用JWPlayer API静音
        try {
            if (typeof jwplayer === 'function' && jwplayer("mediaplayer")) {
                jwplayer("mediaplayer").setMute(true);
                log("已通过JWPlayer API静音视频");
            }
        } catch (error) {
            log("JWPlayer静音尝试失败,等待视频加载: " + error.message);
        }
    }

    // 初始执行一次静音
    muteAllVideos();

    // 监听视频DOM变化,对新加载的视频执行静音
    const videoObserver = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            if (mutation.addedNodes && mutation.addedNodes.length > 0) {
                // 检查新增节点中是否有视频
                for (let i = 0; i < mutation.addedNodes.length; i++) {
                    const node = mutation.addedNodes[i];
                    // 如果节点本身是视频
                    if (node.nodeName && node.nodeName.toLowerCase() === 'video') {
                        node.muted = true;
                        log("检测到新视频已加载,已自动静音");
                    }
                    // 如果是容器节点,检查其中的视频
                    else if (node.getElementsByTagName) {
                        const newVideos = node.getElementsByTagName('video');
                        if (newVideos.length > 0) {
                            for (let j = 0; j < newVideos.length; j++) {
                                newVideos[j].muted = true;
                                log("检测到容器中的新视频,已自动静音");
                            }
                        }
                    }
                }
            }
        });

        // 每次DOM变化都尝试使用JWPlayer API静音
        try {
            if (typeof jwplayer === 'function' && jwplayer("mediaplayer")) {
                jwplayer("mediaplayer").setMute(true);
            }
        } catch (error) {
            // 忽略错误,JWPlayer可能还未加载
        }
    });

    // 观察整个文档的变化
    videoObserver.observe(document.body, {
        childList: true,
        subtree: true
    });

    // 周期性检查以确保视频保持静音状态
    setInterval(muteAllVideos, 2000);

    log("全局视频静音功能已初始化");
}

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址