cela-自动学习脚本模拟版

cela自动学习脚本,支持视频自动播放、进度监控、课程自动切换,支持课程列表页面批量学习。

// ==UserScript==
// @name         cela-自动学习脚本模拟版
// @namespace    https://github.com/Moker32/
// @version      2.19.1
// @description  cela自动学习脚本,支持视频自动播放、进度监控、课程自动切换,支持课程列表页面批量学习。
// @author       Moker32
// @license      GPL-3.0-or-later
// @run-at       document-start
// @match        https://cela.e-celap.cn/page.html#/pc/nc/pagecourse/coursePlayer*
// @match        https://cela.e-celap.cn/page.html#/pc/nc/pagecourse/courseList*
// @match        https://cela.e-celap.cn/page.html#*
// @match        https://cela.e-celap.cn/ncIndex.html#/pc/nc/page/pd/pdchanel/specialdetail*
// @match        https://cela.e-celap.cn/ncIndex.html#*
// @match        https://cela.e-celap.cn/*
// @grant        GM_info
// @run-at       document-idle
// ==/UserScript==


(function() {
    'use strict';

// 新增:拦截"离开网站"弹窗 - 增强版 (已精简)
    function disableBeforeUnload() {
    console.log('🛡️ 启动终极版弹窗拦截机制 (策略B: 全自动模式)...');

    // 核心函数:包装指定窗口的 unload 事件,保留其功能但禁用弹窗
    function forceDisableUnload(win) {
        if (!win) return;
        try {
            // --- 策略1: 强制设为 null (基础清理) ---
            win.onbeforeunload = null;
            win.onunload = null;

            // --- 策略B: 使用 getter/setter 替换属性,巧妙地让所有赋值失效以实现全自动 ---
            Object.defineProperty(win, 'onbeforeunload', {
            get: function() {
                    return null; // 永远返回 null
                },
                set: function() {
                    console.log('🚫 (策略B) 成功拦截并忽略了一次 onbeforeunload 的赋值!');
                    // 什么也不做,直接忽略赋值,以此来阻止最终保存和弹窗
                },
                configurable: true // 保持可配置以遵守代理规则
            });
            Object.defineProperty(win, 'onunload', {
            get: function() {
                return null;
            },
                set: function() {
                    console.log('🚫 (策略B) 成功拦截并忽略了一次 onunload 的赋值!');
            },
            configurable: true
        });
        
            // --- 策略2: 拦截 addEventListener (作为补充) ---
            const originalAddEventListener = win.addEventListener;
            win.addEventListener = function(type, listener, options) {
                if (type === 'beforeunload' || type === 'unload') {
                    console.log('🚫 (策略B) 成功拦截并忽略了一个 beforeunload 事件监听器的添加!');
                    return; // 直接阻止添加
                }
                originalAddEventListener.call(win, type, listener, options);
            };
        } catch (e) {
            console.warn('⚠️ 在窗口上设置包装器失败:', e.message);
        }
    }

    // 1. 处理主窗口 (使用 unsafeWindow 冲破沙箱)
    forceDisableUnload(unsafeWindow);

    // 2. 处理已存在的 iframe
    document.querySelectorAll('iframe').forEach(iframe => {
        // iframe 加载需要时间,确保在加载后执行
         if (iframe.contentWindow) {
            forceDisableUnload(iframe.contentWindow);
        } else {
            iframe.addEventListener('load', () => {
                 forceDisableUnload(iframe.contentWindow);
            }, { once: true });
        }
    });

    // 3. 使用 MutationObserver 监控未来动态添加的 iframe
    const observer = new MutationObserver((mutations) => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.tagName === 'IFRAME') {
                    console.log('✅ 检测到新的 iframe,准备拦截其弹窗事件...');
                    node.addEventListener('load', () => {
                         forceDisableUnload(node.contentWindow);
                         console.log('✅ 新 iframe 的弹窗事件已拦截。');
                    }, { once: true });
                }
            });
            });
        });
        
    // 启动监控
    // 修复:确保在 body 加载后再启动监控
    if (document.body) {
         observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    } else {
        window.addEventListener('DOMContentLoaded', () => {
             observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        }, { once: true });
    }


    console.log('🛡️ 终极版弹窗拦截机制已完全启动。');
    }

    // 配置参数 - 优化:支持用户自定义配置
    const DEFAULT_CONFIG = {
        // 基础设置
        checkInterval: 3000,          // 检查间隔(ms) - 优化性能,降低CPU占用
        progressCheckInterval: 5000,  // 进度检查间隔(ms) - 优化性能,合理检查频率
        maxWaitTime: 600000,         // 最大等待时间(10分钟) - 延长等待时间
        
        // 自动化设置
        autoPlay: true,              // 自动播放视频
        autoSwitchCourse: true,      // 自动切换课程
        completionDelay: 5000,       // 课程完成后的延迟(毫秒),以确保最终进度上报
        
        // 进度保存设置 - 改为纯视频事件驱动
        enhancedProgressSave: true,  // 启用增强进度保存(基于视频事件)
        
          // 防检测设置 - 优化以提高效率但保持安全
        enableRandomDelay: true,     // 启用随机延迟
        minDelay: 500,              // 最小延迟 - 减少等待时间
        maxDelay: 1500,             // 最大延迟 - 减少等待时间
        
        // 音频设置
        enforceGlobalMute: true,     // 强制全局静音播放
        
          // 调试设置
        debugMode: false,            // 调试模式
        showProgressIndicator: false, // 显示进度指示器
        showConsoleLog: true,       // 显示控制台日志UI
        maxLogEntries: 20,          // 最大显示日志条数
        
        // 课程状态管理设置
        useCourseName: true,        // 使用课程名称作为唯一ID
        skipCompletedCourses: true, // 跳过已完成的课程
        autoMarkCompleted: true,    // 自动标记100%进度的课程为已完成
        courseStatusStorageKey: 'china_cadre_course_status', // 课程状态存储键
        
        // DOM选择器配置 - 优化:集中管理所有选择器
        selectors: {
            // 视频播放器相关
            videoPlayer: '#emiya-video video',
            videoContainer: '#emiya-video',
            
            // 进度相关
            progressCircle: '.el-progress--circle[aria-valuenow]',
            progressText: '.el-progress__text',
            
            // 课程信息
            courseTitle: '.course-title, .video-title, h1, .title',
            courseName: '[class*="title"], [class*="name"]',
            
            // 课程列表
            courseList: 'ul li a[href*="coursePlayer"], .course-item a, a[href*="/course/"]',
            courseListContainer: 'ul, .course-list, .list-container',
            
            // 导航和控制
            nextButton: '.next-btn, [class*="next"], button[title*="下一"]',
            playButton: '.play-btn, [class*="play"], button[title*="播放"]',
            
            // 弹窗和模态框
            modal: '.el-dialog, .modal, .popup',
            closeButton: '.el-dialog__close, .close-btn, .modal-close'
        }
    };

    // 配置管理器 - 新增:支持用户自定义配置
    class ConfigManager {
        constructor() {
            this.storageKey = 'china_cadre_script_config';
            this.config = this.loadConfig();
        }

        loadConfig() {
            try {
                const stored = localStorage.getItem(this.storageKey);
                const userConfig = stored ? JSON.parse(stored) : {};
                return { ...DEFAULT_CONFIG, ...userConfig };
            } catch (error) {
                console.error('❌ 加载用户配置失败:', error);
                return { ...DEFAULT_CONFIG };
            }
        }

        saveConfig() {
            try {
                const configToSave = { ...this.config };
                delete configToSave.selectors; // 不保存选择器配置,始终使用默认值
                localStorage.setItem(this.storageKey, JSON.stringify(configToSave));
                console.log('💾 用户配置已保存');
            } catch (error) {
                console.error('❌ 保存用户配置失败:', error);
            }
        }

        updateConfig(key, value) {
            this.config[key] = value;
            this.saveConfig();
        }

        getConfig(key) {
            return this.config[key];
        }

        getAllConfig() {
            return { ...this.config };
        }

        resetToDefault() {
            this.config = { ...DEFAULT_CONFIG };
            localStorage.removeItem(this.storageKey);
            console.log('🔄 配置已重置为默认值');
        }
    }

    // 初始化配置管理器
    const configManager = new ConfigManager();
    const CONFIG = configManager.getAllConfig();

    // 启动弹窗拦截,必须在CONFIG定义之后执行
    disableBeforeUnload();

    // 课程状态管理器
    class CourseStatusManager {
        constructor() {
            this.storageKey = CONFIG.courseStatusStorageKey;
            this.courseStatuses = this.loadCourseStatuses();
        }

        // 从localStorage加载课程状态
        loadCourseStatuses() {
            try {
                const stored = localStorage.getItem(this.storageKey);
                return stored ? JSON.parse(stored) : {};
            } catch (error) {
                console.error('❌ 加载课程状态失败:', error);
                return {};
            }
        }

        // 保存课程状态到localStorage
        saveCourseStatuses() {
            try {
                localStorage.setItem(this.storageKey, JSON.stringify(this.courseStatuses));
                console.log('💾 课程状态已保存');
            } catch (error) {
                console.error('❌ 保存课程状态失败:', error);
            }
        }

        // 获取课程唯一ID(使用课程名称)
        getCourseId(courseName) {
            if (typeof courseName !== 'string' || !courseName) {
                // 如果课程名称无效,返回一个唯一的、安全的ID,防止后续操作出错
                return `invalid_course_id_${Date.now()}_${Math.random()}`;
            }
            return courseName.trim().replace(/\s+/g, '_');
        }

        // 记录课程状态
        setCourseStatus(courseName, status) {
            const courseId = this.getCourseId(courseName);
            if (!this.courseStatuses[courseId]) {
                this.courseStatuses[courseId] = {};
            }
            
            this.courseStatuses[courseId] = {
                ...this.courseStatuses[courseId],
                name: courseName,
                status: status,
                lastUpdate: new Date().toISOString()
            };
            
            this.saveCourseStatuses();
            console.log(`📝 课程状态已更新: ${courseName} -> ${status}`);
        }

        // 获取课程状态
        getCourseStatus(courseName) {
            const courseId = this.getCourseId(courseName);
            return this.courseStatuses[courseId] || null;
        }

        // 检查课程是否已完成
        isCourseCompleted(courseName) {
            const status = this.getCourseStatus(courseName);
            return status && status.status === 'completed';
        }

        // 标记课程为已完成
        markCourseCompleted(courseName) {
            this.setCourseStatus(courseName, 'completed');
        }

        // 标记课程为进行中
        markCourseInProgress(courseName) {
            this.setCourseStatus(courseName, 'in_progress');
        }

        // 获取所有课程状态
        getAllCourseStatuses() {
            return this.courseStatuses;
        }

        // 清除所有课程状态
        clearAllStatuses() {
            this.courseStatuses = {};
            this.saveCourseStatuses();
            console.log('🗑️ 所有课程状态已清除');
        }

        // 获取统计信息
        getStatistics() {
            const statuses = Object.values(this.courseStatuses);
            const completed = statuses.filter(s => s.status === 'completed').length;
            const inProgress = statuses.filter(s => s.status === 'in_progress').length;
            const total = statuses.length;

            return {
                total,
                completed,
                inProgress,
                completionRate: total > 0 ? (completed / total * 100).toFixed(1) : 0
            };
        }
    }



    // Aura设计系统 - 精polish版UI样式
    const SCRIPT_STYLES = `
        :root {
            --aura-font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Source Han Sans SC', 'Helvetica Neue', 'Arial', sans-serif;
            --aura-primary: #007AFF;
            --aura-success: #34C759;
            --aura-warning: #FF9500;
            --aura-danger: #FF3B30;
            --aura-text-primary: #1D1D1F;
            --aura-text-secondary: #6E6E73;
            --aura-bg-glass: rgba(252, 252, 252, 0.8);
            --aura-bg-accent: rgba(235, 235, 245, 0.7);
            --aura-border: rgba(0, 0, 0, 0.08);
            --aura-shadow: 0px 10px 35px rgba(0, 0, 0, 0.08);
            --aura-radius-lg: 18px;
            --aura-radius-md: 10px;
            --aura-transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
        }

        .aura-panel, .auto-learn-container {
            position: fixed;
            font-family: var(--aura-font-family);
            color: var(--aura-text-primary);
            background-color: var(--aura-bg-glass);
            backdrop-filter: blur(24px) saturate(180%);
            -webkit-backdrop-filter: blur(24px) saturate(180%);
            border: 1px solid var(--aura-border);
            border-radius: var(--aura-radius-lg);
            box-shadow: var(--aura-shadow);
            z-index: 999999;
            display: flex;
            flex-direction: column;
            transition: height 0.3s cubic-bezier(0.4, 0, 0.2, 1), width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            overflow: hidden;
        }

        .aura-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 16px;
            border-bottom: 1px solid var(--aura-border);
            cursor: move;
            flex-shrink: 0;
        }

        .aura-title, .auto-learn-title { font-size: 16px; font-weight: 600; }

        .aura-header-controls { display: flex; align-items: center; gap: 4px; }

        .aura-icon-btn, .auto-learn-header-control-btn {
            display: flex; align-items: center; justify-content: center;
            width: 30px; height: 30px; padding: 0; border: none;
            background-color: transparent;
            border-radius: var(--aura-radius-md);
            color: var(--aura-text-secondary);
            cursor: pointer; transition: var(--aura-transition);
        }
        .aura-icon-btn:hover, .auto-learn-header-control-btn:hover {
            background-color: var(--aura-bg-accent);
            color: var(--aura-text-primary);
            transform: scale(1.05);
        }

        .aura-icon { width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; }
        .aura-icon svg { width: 100%; height: 100%; }

        .aura-stats-bar, .auto-learn-stats {
            padding: 10px 16px;
            border-bottom: 1px solid var(--aura-border);
            font-size: 13px; color: var(--aura-text-secondary);
            text-align: center; font-weight: 500; flex-shrink: 0;
        }

        .aura-content, .auto-learn-content-container {
            flex: 1 1 auto; overflow-y: auto;
            transition: opacity 0.2s ease-in, max-height 0.3s ease-out;
            max-height: 500px; opacity: 1;
        }
        .aura-content.collapsed, .auto-learn-content-container.collapsed { max-height: 0; opacity: 0; }

        .aura-course-list, .auto-learn-course-list { list-style: none; padding: 8px; margin: 0; }

        .aura-course-item, .auto-learn-course-item {
            display: flex; align-items: center; gap: 12px;
            padding: 10px 12px;
            border-radius: var(--aura-radius-md);
            cursor: pointer; transition: var(--aura-transition);
            text-decoration: none; color: var(--aura-text-primary);
            font-size: 14px; margin-bottom: 4px;
        }
        .aura-course-item:hover, .auto-learn-course-item:hover { background-color: var(--aura-bg-accent); }
        .aura-course-item.in-progress, .auto-learn-course-item.in-progress { font-weight: 600; color: var(--aura-primary); background-color: rgba(0, 122, 255, 0.1); }
        .aura-course-item.completed, .auto-learn-course-item.completed { color: var(--aura-text-secondary); }
        .aura-course-item.completed .aura-course-name { text-decoration: line-through; }

        .aura-course-status-icon { width: 20px; height: 20px; flex-shrink: 0; }
        .aura-course-status-icon .aura-icon { width: 100%; height: 100%; }

        .aura-log-entry, .auto-learn-log-entry {
            padding: 8px 16px;
            font-size: 13px; line-height: 1.5;
            color: var(--aura-text-secondary);
            border-bottom: 1px solid var(--aura-border);
            transition: background-color 0.3s;
        }
        .aura-log-entry.latest { background-color: rgba(0, 122, 255, 0.08); }
        .aura-log-entry strong, .auto-learn-log-entry strong { font-weight: 500; color: var(--aura-text-primary); }
        .auto-learn-log-entry.latest-log-highlight { background-color: rgba(0, 122, 255, 0.08); }

        .aura-footer, .auto-learn-footer {
            padding: 12px; border-top: 1px solid var(--aura-border);
            flex-shrink: 0; transition: var(--aura-transition);
            max-height: 100px; opacity: 1; overflow: hidden;
        }
        .aura-footer.collapsed, .auto-learn-footer.collapsed { max-height: 0; opacity: 0; padding-top: 0; padding-bottom: 0; }

        .aura-button, .auto-learn-button {
            width: 100%; padding: 12px; border: none;
            border-radius: var(--aura-radius-md);
            font-size: 14px; font-weight: 600;
            cursor: pointer; transition: var(--aura-transition);
            display: flex; align-items: center; justify-content: center; gap: 8px;
        }
        .aura-button .aura-icon { width: 16px; height: 16px; }
        .aura-button.primary, .auto-learn-button.primary { background-color: var(--aura-primary); color: white; }
        .aura-button.primary:hover, .auto-learn-button.primary:hover { transform: scale(1.02); box-shadow: 0 4px 15px rgba(0, 122, 255, 0.2); }
        .aura-button.success, .auto-learn-button.success { background-color: var(--aura-success); color: white; }
        .auto-learn-button.warning { background-color: var(--aura-warning); color: white; }
        .auto-learn-button.danger { background-color: var(--aura-danger); color: white; }
        .auto-learn-button:disabled { opacity: 0.6; cursor: not-allowed; }

        .aura-modal-overlay, .auto-learn-modal-overlay {
            position: fixed; top: 0; left: 0; right: 0; bottom: 0;
            background: rgba(0, 0, 0, 0.3);
            backdrop-filter: blur(4px);
            -webkit-backdrop-filter: blur(4px);
            z-index: 1000000; display: flex; align-items: center; justify-content: center;
        }

        .aura-modal, .auto-learn-modal {
            background: var(--aura-bg-glass);
            backdrop-filter: blur(24px) saturate(180%);
            -webkit-backdrop-filter: blur(24px) saturate(180%);
            border-radius: var(--aura-radius-lg);
            box-shadow: var(--aura-shadow);
            max-width: 500px; width: 90vw;
            max-height: 90vh; overflow: auto; position: relative;
            padding: 24px;
        }

        .aura-modal-close-btn {
            position: absolute; top: 12px; right: 12px;
            width: 32px; height: 32px;
            display: flex; align-items: center; justify-content: center;
            border-radius: 50%;
            background-color: var(--aura-bg-accent);
            color: var(--aura-text-secondary);
            cursor: pointer; transition: var(--aura-transition);
            border: none; padding: 0;
        }
        .aura-modal-close-btn:hover { transform: scale(1.05) rotate(90deg); color: var(--aura-text-primary); }
        .aura-modal-close-btn .aura-icon { width: 16px; height: 16px; }

        .aura-settings-panel, .auto-learn-settings-panel { max-height: 450px; overflow-y: auto; padding-right: 8px; }

        .aura-setting-group-title {
            margin: 20px 0 10px 0; padding-bottom: 6px;
            border-bottom: 1px solid var(--aura-border);
            color: var(--aura-text-primary); font-size: 14px; font-weight: 600;
        }
        .aura-setting-group-title:first-of-type { margin-top: 0; }

        .aura-setting-item, .auto-learn-setting-item {
            display: flex; justify-content: space-between; align-items: flex-start;
            padding: 14px 4px;
            border-bottom: 1px solid var(--aura-border);
        }
        .aura-setting-item:last-child, .auto-learn-setting-item:last-child { border-bottom: none; }

        .aura-setting-label-group { display: flex; flex-direction: column; padding-right: 16px; }
        .aura-setting-label, .auto-learn-setting-label { font-weight: 500; color: var(--aura-text-primary); font-size: 14px; }
        .aura-setting-description, .auto-learn-setting-description { font-size: 12px; color: var(--aura-text-secondary); margin-top: 4px; }

        .aura-setting-control, .auto-learn-setting-control { display: flex; align-items: center; flex-shrink: 0; padding-top: 2px; }

        .aura-checkbox, .auto-learn-checkbox { width: 20px; height: 20px; cursor: pointer; accent-color: var(--aura-primary); }

        .aura-input, .auto-learn-input {
            padding: 6px 10px; border: 1px solid var(--aura-border);
            border-radius: var(--aura-radius-md); font-size: 13px;
            width: 80px; background-color: var(--aura-bg-accent);
            transition: var(--aura-transition);
        }
        .aura-input:focus, .auto-learn-input:focus { background-color: white; border-color: var(--aura-primary); outline: none; }

        @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
        .aura-icon.spinning { animation: spin 1.5s linear infinite; }
    `;

    // 注入样式表 - 优化:在脚本初始化时注入所有样式
    function injectStyles() {
        const styleSheet = document.createElement("style");
        styleSheet.type = "text/css";
        styleSheet.id = "auto-learning-styles";
        styleSheet.textContent = SCRIPT_STYLES;
        
        // 确保样式表被正确插入
        if (document.head) {
            document.head.appendChild(styleSheet);
        } else {
            // 如果head还没有加载,等待DOM加载完成
            document.addEventListener('DOMContentLoaded', () => {
                document.head.appendChild(styleSheet);
            });
        }
        
        console.log('🎨 样式表已注入');
    }

    // 统一UI工具类
    class UIBuilder {
        static ICONS = {
            CHEVRON_DOWN: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"></polyline></svg>`,
            CHEVRON_UP: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"></polyline></svg>`,
            SETTINGS: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>`,
            RESET: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg>`,
            HELP: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>`,
            CLOSE: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>`,
            PLAY: `<svg viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7z"></path></svg>`,
            SUCCESS: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>`,
            IN_PROGRESS: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="2" x2="12" y2="6"></line><line x1="12" y1="18" x2="12" y2="22"></line><line x1="4.93" y1="4.93" x2="7.76" y2="7.76"></line><line x1="16.24" y1="16.24" x2="19.07" y2="19.07"></line><line x1="2" y1="12" x2="6" y2="12"></line><line x1="18" y1="12" x2="22" y2="12"></line><line x1="4.93" y1="19.07" x2="7.76" y2="16.24"></line><line x1="16.24" y1="7.76" x2="19.07" y2="4.93"></line></svg>`,
            WARNING: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>`,
            ERROR: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="15" y1="9" x2="9" y2="15"></line><line x1="9" y1="9" x2="15" y2="15"></line></svg>`,
            INFO: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="16" x2="12" y2="12"></line><line x1="12" y1="8" x2="12.01" y2="8"></line></svg>`
        };

        static createIcon(iconName, options = {}) {
            const iconContainer = document.createElement('div');
            const svgString = this.ICONS[iconName];
            if (!svgString) return null;

            iconContainer.className = 'aura-icon ' + (options.className || '');
            iconContainer.innerHTML = svgString;

            if (options.color) {
                iconContainer.style.color = options.color;
            }

            return iconContainer;
        }

        static createContainer(options = {}) {
            const container = document.createElement('div');
            
            // 优化:使用CSS类而不是内联样式
            container.className = 'auto-learn-container' + (options.className ? ' ' + options.className : '');
            
            if (options.id) container.id = options.id;
            
            // 只处理位置相关的内联样式,其他样式通过CSS类处理
            if (options.style) {
                const positionStyles = {};
                const allowedInlineStyles = ['top', 'left', 'right', 'bottom', 'width', 'height', 'maxHeight', 'maxWidth'];
                
                Object.entries(options.style).forEach(([key, value]) => {
                    if (allowedInlineStyles.includes(key)) {
                        positionStyles[this.camelToKebab(key)] = value;
                    }
                });
                
                container.style.cssText = Object.entries(positionStyles)
                    .map(([key, value]) => `${key}: ${value}`)
                    .join('; ');
            }

            return container;
        }

        static createButton(text, options = {}) {
            const button = document.createElement('button');
            
            // 优化:使用CSS类而不是内联样式
            let className = 'auto-learn-button';
            
            // 根据选项添加相应的CSS类
            if (options.variant) {
                className += ` ${options.variant}`;
            } else if (options.style) {
                // 为了向后兼容,检查内联样式中的背景色
                const bgColor = options.style.background || options.style.backgroundColor;
                if (bgColor === '#007AFF' || bgColor === '#4A90E2') className += ' primary';
                else if (bgColor === '#34C759' || bgColor === '#5CB85C') className += ' success';
                else if (bgColor === '#FF9500' || bgColor === '#F0AD4E') className += ' warning';
                else if (bgColor === '#FF3B30' || bgColor === '#D9534F') className += ' danger';
            }
            
            if (options.className) {
                className += ` ${options.className}`;
            }
            
            button.className = className;

            // 处理图标
            if (options.icon) {
                const icon = this.createIcon(options.icon);
                if (icon) {
                    button.appendChild(icon);
                }
            }

            // 添加文本
            const textSpan = document.createElement('span');
            textSpan.textContent = text;
            button.appendChild(textSpan);

            // 只处理特殊的内联样式(如尺寸、位置等)
            if (options.style) {
                const allowedInlineStyles = ['width', 'height', 'minWidth', 'maxWidth', 'padding', 'margin', 'fontSize', 'position', 'top', 'right', 'bottom', 'left'];
                const inlineStyles = {};
                
                Object.entries(options.style).forEach(([key, value]) => {
                    if (allowedInlineStyles.includes(key)) {
                        inlineStyles[this.camelToKebab(key)] = value;
                    }
                });
                
                if (Object.keys(inlineStyles).length > 0) {
                    button.style.cssText = Object.entries(inlineStyles)
                        .map(([key, value]) => `${key}: ${value}`)
                        .join('; ');
                }
            }

            // 事件处理
            if (options.onClick) {
                button.addEventListener('click', options.onClick);
            }

            if (options.title) {
                button.title = options.title;
            }

            if (options.disabled) {
                button.disabled = true;
            }

            return button;
        }

        static createTitle(text, options = {}) {
            const title = document.createElement('div');
            
            // 优化:使用CSS类而不是内联样式
            title.className = 'auto-learn-title' + (options.className ? ' ' + options.className : '');
            title.textContent = text;
            
            // 只处理特殊的内联样式
            if (options.style) {
                const allowedInlineStyles = ['fontSize', 'textAlign', 'margin', 'padding'];
                const inlineStyles = {};
                
                Object.entries(options.style).forEach(([key, value]) => {
                    if (allowedInlineStyles.includes(key)) {
                        inlineStyles[this.camelToKebab(key)] = value;
                    }
                });
                
                if (Object.keys(inlineStyles).length > 0) {
                    title.style.cssText = Object.entries(inlineStyles)
                        .map(([key, value]) => `${key}: ${value}`)
                .join('; ');
                }
            }

            return title;
        }

        static createModal(content, options = {}) {
            const overlay = document.createElement('div');
            
            // 优化:使用CSS类而不是内联样式
            overlay.className = 'auto-learn-modal-overlay';

            const modal = document.createElement('div');
            modal.className = 'auto-learn-modal';
            
            // 处理模态框的特殊样式
            if (options.modalStyle) {
                const allowedInlineStyles = ['maxWidth', 'maxHeight', 'width', 'height'];
                const inlineStyles = {};
                
                Object.entries(options.modalStyle).forEach(([key, value]) => {
                    if (allowedInlineStyles.includes(key)) {
                        inlineStyles[this.camelToKebab(key)] = value;
                    }
                });
                
                if (Object.keys(inlineStyles).length > 0) {
                    modal.style.cssText = Object.entries(inlineStyles)
                        .map(([key, value]) => `${key}: ${value}`)
                        .join('; ');
                }
            }

            if (typeof content === 'string') {
                modal.innerHTML = content;
            } else {
                modal.appendChild(content);
            }

            if (options.closable !== false) {
                const closeBtn = this.createButton('', {
                    icon: 'CLOSE',
                    className: 'aura-modal-close-btn',
                    onClick: () => {
                        overlay.remove();
                        if (options.onClose) options.onClose();
                    }
                });
                modal.appendChild(closeBtn);
            }

            overlay.appendChild(modal);

            if (options.closeOnOverlay !== false) {
                overlay.addEventListener('click', (e) => {
                    if (e.target === overlay) {
                        overlay.remove();
                        if (options.onClose) options.onClose();
                    }
                });
            }

            return overlay;
        }

        static camelToKebab(str) {
            return str.replace(/([A-Z])/g, '-$1').toLowerCase();
        }

        // 新增:创建设置面板 - 优化:UI驱动的配置管理,分组显示
        static createSettingsPanel() {
            const settingsConfig = {
                '通用设置': [
                    {
                        key: 'enforceGlobalMute',
                        label: '强制静音',
                        description: '强制所有视频静音播放',
                        type: 'checkbox'
                    },
                    {
                        key: 'maxLogEntries',
                        label: '最大日志条数',
                        description: '日志面板显示的最大条目数',
                        type: 'number',
                        min: 5,
                        max: 50
                    }
                ],
                '自动化行为': [
                    {
                        key: 'autoPlay',
                        label: '自动播放',
                        description: '自动播放视频',
                        type: 'checkbox'
                    },
                    {
                        key: 'autoSwitchCourse',
                        label: '自动切换课程',
                        description: '完成当前课程后自动切换到下一个',
                        type: 'checkbox'
                    }
                ],
                '高级设置': [
                    {
                        key: 'enableRandomDelay',
                        label: '随机延迟',
                        description: '启用随机延迟以避免检测',
                        type: 'checkbox'
                    },
                    {
                        key: 'checkInterval',
                        label: '检查间隔 (ms)',
                        description: '视频状态检查间隔时间',
                        type: 'number',
                        min: 1000,
                        max: 10000
                    },
                    {
                        key: 'progressCheckInterval',
                        label: '进度检查间隔 (ms)',
                        description: '学习进度检查间隔时间',
                        type: 'number',
                        min: 1000,
                        max: 15000
                    }
                ]
            };

            const panel = document.createElement('div');
            panel.className = 'auto-learn-settings-panel';

            // 优化:按分组渲染设置项
            Object.entries(settingsConfig).forEach(([groupTitle, settings]) => {
                // 创建分组标题
                const groupHeader = document.createElement('h4');
                groupHeader.textContent = groupTitle;
                groupHeader.style.cssText = `
                    margin: 16px 0 8px 0;
                    padding-bottom: 4px;
                    border-bottom: 1px solid var(--aura-border);
                    color: var(--aura-text-primary);
                    font-size: 14px;
                    font-weight: 600;
                `;
                if (groupTitle !== Object.keys(settingsConfig)[0]) {
                    panel.appendChild(groupHeader);
                } else {
                    // 第一个分组不需要上边距
                    groupHeader.style.marginTop = '0';
                    panel.appendChild(groupHeader);
                }

                // 渲染该分组下的设置项
                settings.forEach(setting => {
                const item = document.createElement('div');
                item.className = 'auto-learn-setting-item';

                // 创建标签组容器
                const labelGroup = document.createElement('div');
                labelGroup.className = 'aura-setting-label-group';

                const label = document.createElement('div');
                label.className = 'auto-learn-setting-label';
                label.textContent = setting.label;
                labelGroup.appendChild(label);

                if (setting.description) {
                    const desc = document.createElement('div');
                    desc.className = 'auto-learn-setting-description';
                    desc.textContent = setting.description;
                    labelGroup.appendChild(desc);
                }

                const controlDiv = document.createElement('div');
                controlDiv.className = 'auto-learn-setting-control';

                if (setting.type === 'checkbox') {
                    const checkbox = document.createElement('input');
                    checkbox.type = 'checkbox';
                    checkbox.className = 'auto-learn-checkbox';
                    checkbox.checked = configManager.getConfig(setting.key);
                    checkbox.addEventListener('change', (e) => {
                        configManager.updateConfig(setting.key, e.target.checked);
                        console.log(`⚙️ 配置已更新: ${setting.key} = ${e.target.checked}`);
                    });
                    controlDiv.appendChild(checkbox);
                } else if (setting.type === 'number') {
                    const input = document.createElement('input');
                    input.type = 'number';
                    input.className = 'auto-learn-input';
                    input.value = configManager.getConfig(setting.key);
                    input.min = setting.min;
                    input.max = setting.max;
                    input.addEventListener('change', (e) => {
                        const value = parseInt(e.target.value);
                        if (value >= setting.min && value <= setting.max) {
                            configManager.updateConfig(setting.key, value);
                            console.log(`⚙️ 配置已更新: ${setting.key} = ${value}`);
                        }
                    });
                    controlDiv.appendChild(input);
                }

                item.appendChild(labelGroup);
                item.appendChild(controlDiv);
                panel.appendChild(item);
                });
            });

            // 添加重置按钮
            const resetDiv = document.createElement('div');
            resetDiv.style.marginTop = '16px';
            resetDiv.style.textAlign = 'center';

            const resetBtn = this.createButton('重置为默认值', {
                variant: 'warning',
                style: { width: '100%' },
                onClick: () => {
                    if (confirm('确定要重置所有配置为默认值吗?')) {
                        configManager.resetToDefault();
                        alert('配置已重置,请刷新页面以应用更改。');
                    }
                }
            });
            resetDiv.appendChild(resetBtn);
            panel.appendChild(resetDiv);

            return panel;
        }

        static updateCourseStats() {
            const statsContainer = document.getElementById('learning-stats-container');
            if (!statsContainer) return;

            const stats = courseStatusManager.getStatistics();
            const { completed = 0, total = 0, inProgress = 0 } = stats;

            if (total === 0 && inProgress === 0) {
                 statsContainer.textContent = '暂无课程,请先访问课程列表页';
                 return;
            }
            
            const remaining = total - completed;
            statsContainer.textContent = `已完成: ${completed} | 剩余: ${remaining} | 总计: ${total}`;
            this.updateCourseListDisplay();
        }

        static updateCourseListDisplay() {
            const courseListContainer = document.getElementById('course-list-items-container');
            if (!courseListContainer) return;

            const courseElements = SharedUtils.findCourseElements();
            const courses = courseElements.map(courseInfo => ({
                name: courseInfo.name,
                href: courseInfo.href,
                isCompleted: courseStatusManager.isCourseCompleted(courseInfo.name),
                status: courseStatusManager.getCourseStatus(courseInfo.name)?.status || 'not_started'
            }));

            this.renderCourseList(courseListContainer, courses);
        }

        static addLogEntry(message, type = 'info') {
            const logDisplayContainer = document.getElementById('auto-learning-log-player');
            const scrollableContainer = document.getElementById('universal-content-container');

            if (!logDisplayContainer || !scrollableContainer) return;

            const prevHighlight = logDisplayContainer.querySelector('.latest-log-highlight');
            if (prevHighlight) {
                prevHighlight.classList.remove('latest-log-highlight');
            }

            const typeToColor = {
                info: 'var(--aura-text-secondary)',
                success: 'var(--aura-success)',
                warning: 'var(--aura-warning)',
                error: 'var(--aura-danger)'
            };
            const color = typeToColor[type.toLowerCase()] || 'var(--aura-text-secondary)';

            const entry = document.createElement('div');
            
            // 优化:使用CSS类而不是内联样式
            entry.className = 'auto-learn-log-entry latest-log-highlight';
            entry.style.color = color; // 颜色仍需内联设置,因为是动态的
            
            const timestamp = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
            
            // 优化:高亮日志中的关键信息
            let formattedMessage = message;
            // 高亮被引号包裹的课程名称
            formattedMessage = formattedMessage.replace(/"(.*?)"/g, '<strong style="color: #2c3e50;">"$1"</strong>');
            // 高亮百分比
            formattedMessage = formattedMessage.replace(/(\d+%)/g, '<strong style="color: #27ae60;">$1</strong>');
            // 高亮数字(如课程数量)
            formattedMessage = formattedMessage.replace(/(\d+)(?=\s*(?:个|门|课程|项目))/g, '<strong style="color: #3498db;">$1</strong>');
            // 高亮状态关键词
            formattedMessage = formattedMessage.replace(/(已完成|进行中|失败|成功|开始|结束)/g, '<strong>$1</strong>');
            
            entry.innerHTML = `<span style="font-family: monospace; font-size: 12px; color: #999; margin-right: 5px;">[${timestamp}]</span>${formattedMessage}`;

            logDisplayContainer.appendChild(entry);

            const maxEntries = CONFIG.maxLogEntries || 20;
            while (logDisplayContainer.children.length > maxEntries) {
                logDisplayContainer.removeChild(logDisplayContainer.firstChild);
            }

            scrollableContainer.scrollTop = scrollableContainer.scrollHeight;
        }

        static createUniversalUI(options = {}) {
            const { 
                pageType = 'player',
                courses = [],
                onStartLearning = null,
                onReset = null,
                onHelp = null
            } = options;

            const container = this.createContainer({
                id: 'auto-learning-universal-ui',
                style: {
                    bottom: '20px',
                    right: '20px',
                    width: '380px',
                    height: '550px',
                    overflow: 'hidden',
                    padding: '0'
                }
            });

            // Header
            const header = document.createElement('div');
            header.style.cssText = `
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding: 8px 12px;
                background-color: var(--aura-bg-accent);
                border-bottom: 1px solid var(--aura-border);
                flex-shrink: 0;
            `;
            const title = this.createTitle('自动学习助手', {
                style: {
                    fontSize: '16px',
                    fontWeight: '600',
                    margin: '0',
                    border: 'none',
                    padding: '0'
                }
            });
            header.appendChild(title);

            const controls = document.createElement('div');
            controls.style.display = 'flex';
            controls.style.gap = '8px';

            const toggleBtn = this.createButton('', {
                icon: 'CHEVRON_DOWN',
                title: '收起/展开',
                className: 'auto-learn-header-control-btn'
            });
            controls.appendChild(toggleBtn);
            
            const resetBtn = this.createButton('', {
                icon: 'RESET',
                title: '重置学习状态',
                onClick: onReset,
                className: 'auto-learn-header-control-btn'
            });
            controls.appendChild(resetBtn);

            const helpBtn = this.createButton('', {
                icon: 'HELP',
                title: '帮助',
                onClick: onHelp,
                className: 'auto-learn-header-control-btn'
            });
            controls.appendChild(helpBtn);

            const settingsBtn = this.createButton('', {
                icon: 'SETTINGS',
                title: '设置',
                onClick: () => {
                    const settingsPanel = this.createSettingsPanel();
                    const modal = this.createModal(settingsPanel, {
                        modalStyle: { maxWidth: '500px' }
                    });
                    document.body.appendChild(modal);
                },
                className: 'auto-learn-header-control-btn'
            });
            controls.appendChild(settingsBtn);
            header.appendChild(controls);
            container.appendChild(header);

            // Stats Bar
            const statsContainer = document.createElement('div');
            statsContainer.id = 'learning-stats-container';
            statsContainer.className = 'auto-learn-stats';
            statsContainer.textContent = '统计信息加载中...';
            container.appendChild(statsContainer);

            // Main Content
            const contentContainer = document.createElement('div');
            contentContainer.id = 'universal-content-container';
            contentContainer.className = 'auto-learn-content-container';
            Object.assign(contentContainer.style, {
                flex: '1 1 auto',
                overflowY: 'auto',
                padding: '10px',
            });

            let courseListContainer = null;
            let logContainer = null;

            if (pageType === 'list') {
                courseListContainer = document.createElement('div');
                courseListContainer.id = 'course-list-items-container';
                this.renderCourseList(courseListContainer, courses);
                contentContainer.appendChild(courseListContainer);
            } else {
                logContainer = document.createElement('div');
                logContainer.id = 'auto-learning-log-player';
                logContainer.style.padding = '5px';
                logContainer.textContent = '等待学习开始...';
                contentContainer.appendChild(logContainer);
            }
            container.appendChild(contentContainer);

            // Footer/Action Bar
            if (pageType === 'list') {
                const footer = document.createElement('div');
                footer.className = 'auto-learn-footer';
                footer.style.cssText = `
                    padding: 12px;
                    border-top: 1px solid var(--aura-border);
                    flex-shrink: 0;
                `;
                const mainButton = this.createButton('开始学习', {
                    icon: 'PLAY',
                style: { 
                        width: '100%',
                        background: 'var(--aura-primary)',
                        color: '#ffffff',
                        border: 'none',
                        padding: '10px',
                        fontSize: '14px',
                        fontWeight: 'bold'
                    },
                    title: '点击开始自动学习未完成课程',
                    onClick: onStartLearning
                });

                const firstUncompleted = courses.find(c => !c.isCompleted);
                if (!firstUncompleted) {
                    mainButton.querySelector('span').textContent = '全部完成';
                    mainButton.style.background = 'var(--aura-success)';
                    mainButton.disabled = true;
                }
                footer.appendChild(mainButton);
                container.appendChild(footer);
            }
            
            document.body.appendChild(container);

            // Toggle functionality - 优化:使用平滑动画
            let isExpanded = true;
            const footer = container.querySelector('.auto-learn-footer');

            toggleBtn.addEventListener('click', () => {
                isExpanded = !isExpanded;

                // 使用CSS类切换而不是直接修改样式
                contentContainer.classList.toggle('collapsed', !isExpanded);
                if (footer) {
                    footer.classList.toggle('collapsed', !isExpanded);
                }

                // 计算折叠后的高度
                const headerHeight = header.offsetHeight;
                const statsHeight = statsContainer.offsetHeight;
                const collapsedHeight = headerHeight + statsHeight + 2; // +2px for potential borders/margins

                container.style.height = isExpanded ? '550px' : `${collapsedHeight}px`;
                
                // 更新图标,找到图标元素
                const iconElement = toggleBtn.querySelector('.aura-icon');
                if (iconElement) {
                    iconElement.innerHTML = isExpanded ? this.ICONS.CHEVRON_DOWN : this.ICONS.CHEVRON_UP;
                }
            });

            this.updateCourseStats();
            console.log(`🎨 通用UI创建成功 (${pageType}模式)`);
            return { container, contentContainer, courseListContainer, logContainer };
        }

        static renderCourseList(container, courses) {
            if (!container) return;
            container.innerHTML = '';

            if (!courses || courses.length === 0) {
                container.innerHTML = '<div style="color: var(--aura-text-secondary); padding: 20px; text-align: center;">未发现可学习的课程。</div>';
                return;
            }

            const list = document.createElement('ul');
            list.className = 'aura-course-list auto-learn-course-list';

            courses.forEach((course, index) => {
                const { status, isCompleted } = courseStatusManager.getCourseStatus(course.name) || { status: 'not_started', isCompleted: false };
                const isInProgress = status === 'in_progress';

                const li = document.createElement('li');
                const a = document.createElement('a');
                a.href = course.href || '#';
                
                // 使用新的CSS类
                let className = 'aura-course-item auto-learn-course-item';
                if (isCompleted) className += ' completed';
                else if (isInProgress) className += ' in-progress';
                a.className = className;

                // 创建状态图标
                const statusIconContainer = document.createElement('div');
                statusIconContainer.className = 'aura-course-status-icon';
                if (isCompleted) {
                    statusIconContainer.appendChild(this.createIcon('SUCCESS', { color: 'var(--aura-success)' }));
                } else if (isInProgress) {
                    const progressIcon = this.createIcon('IN_PROGRESS');
                    progressIcon.classList.add('spinning'); // 添加旋转动画
                    statusIconContainer.appendChild(progressIcon);
                }

                // 创建课程名称
                const courseName = document.createElement('span');
                courseName.textContent = course.name || '';

                a.appendChild(statusIconContainer);
                a.appendChild(courseName);

                a.addEventListener('click', (e) => {
                    e.preventDefault();
                    if (!isCompleted) {
                        courseListHandler.startCourse(course);
                    } else {
                        UIBuilder.addLogEntry(`课程 "${course.name}" 已完成,无需重复学习。`, 'info');
                    }
                });

                li.appendChild(a);

                if (isInProgress) {
                    setTimeout(() => li.scrollIntoView({ behavior: 'smooth', block: 'center' }), 100);
                }

                list.appendChild(li);
            });

            container.appendChild(list);
        }
    }

// 共享工具函数
const SharedUtils = {
    /**
     * 从指定上下文元素中按选择器优先级提取文本内容
     * @param {Element} context - 查找的上下文 (例如 document 或某个特定元素)
     * @param {string[]} selectors - 选择器数组
     * @returns {string|null} 找到的文本内容或 null
     */
    findTextContent(context, selectors) {
        for (const selector of selectors) {
            const element = context.querySelector(selector);
            if (element && element.textContent.trim()) {
                return element.textContent.trim();
            }
        }
        return null;
    },

    // 优化版课程元素查找 - 减少冗余代码
    findCourseElements() {
        // 优化选择器,使其更精确,减少重复查找
        const selectors = [
            // 优先使用最明确的、带有唯一属性的父级容器下的条目
            '.specialdetail_catalogue .catalogue_item[ctrl_type="dsf.pdzlcard2"]',
            // 备用选择器
            '.catalogue_content .catalogue_item',
            'a[href*="coursePlayer"]'
        ];

        const allCourses = this.findCoursesWithSelectors(selectors);
        return this.deduplicateCourses(allCourses);
    },

    // 统一的选择器查找方法,减少重复代码
    findCoursesWithSelectors(selectors) {
        const courses = [];

        selectors.forEach(selector => {
            try {
                const elements = document.querySelectorAll(selector);
                console.log(`🎯 "${selector}": ${elements.length}个元素`);

                elements.forEach(el => {
                    const courseInfo = this.extractCourseInfo(el, selector);
                    if (courseInfo && this.isValidCourse(courseInfo)) {
                        courses.push(courseInfo);
                    }
                });
            } catch (error) {
                console.warn(`⚠️ 选择器"${selector}"执行失败:`, error);
            }
        });

        return courses;
    },

    // 统一的课程信息提取方法
    extractCourseInfo(element, selector) {
        const courseInfo = {
            element: element,
            href: element.href || element.getAttribute('href'),
            name: '', // 统一使用 name
            selector: selector,
            isCatalogueItem: selector.includes('catalogue_item'),
            hasDataAttributes: element.hasAttribute('data-course-id') || element.hasAttribute('data-lesson-id')
        };

        // 优先从特定子元素中查找标题
        const titleElement = element.querySelector('.item-title, .title, .name, h3, h4, .course-title');
        if (titleElement) {
            courseInfo.name = titleElement.textContent.trim();
        } else {
            // 如果找不到特定子元素,则使用元素自身的文本或属性作为后备
            courseInfo.name = (element.textContent || element.title || element.getAttribute('title') || element.getAttribute('alt') || '').trim();
        }

        // 如果最终标题为空,则不处理
        if (!courseInfo.name) {
            return null;
        }


        // 根据元素类型提取href
        if (courseInfo.isCatalogueItem && !courseInfo.href) {
            courseInfo.href = `catalogue-item-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
        } else if (courseInfo.hasDataAttributes && !courseInfo.href) {
            courseInfo.href = `data-course-${element.getAttribute('data-course-id') || element.getAttribute('data-lesson-id')}`;
        }

        return courseInfo;
    },

    // 优化版课程验证 - 合并重复的验证逻辑
    isValidCourse(courseInfo) {
        // 在提取阶段已经过滤了无效课程,这里可以简化
        if (!courseInfo || !courseInfo.name) {
            return false;
        }

        const { element, href } = courseInfo;

        // 1. 课程目录条目和有数据属性的元素直接认为有效
        if (courseInfo.isCatalogueItem || courseInfo.hasDataAttributes) {
            return true;
        }

        // 2. 检查onclick事件
        const onclickAttr = element.getAttribute('onclick');
        if (onclickAttr && /course|play|learn/i.test(onclickAttr)) {
            return true;
        }

        // 3. URL验证(合并原有的多个URL检查方法)
        if (href && this.isValidCourseURL(href)) {
            return true;
        }

        // 4. 检查元素结构特征
        const structureSelectors = [
            '.item-title, .course-title, .video-title, .lesson-title',
            '.duration, .time-icon, .course-info, .instructor, .teacher'
        ];

        return structureSelectors.some(sel => element.querySelector(sel) !== null);
    },

    // 简化的URL验证
    isValidCourseURL(href) {
        if (!href || href === '#') return false;

        // 允许特殊标识符和标准课程URL模式
        return href.includes('catalogue-item-') ||
               href.includes('data-course-') ||
               /coursePlayer|pagecourse|\/course\/|play.*course|learn.*course/i.test(href);
    },

    // 课程去重
    deduplicateCourses(courses) {
        const seen = new Set();
        return courses.filter(course => {
            // 恢复原始的、更健壮的去重逻辑
            const titleElement = course.element.querySelector('.item-title, .title, .name, h3, h4, .course-title');
            const key = titleElement ? titleElement.textContent.trim() : (course.href || course.element.textContent.trim());

            if (!key || seen.has(key)) {
                if (CONFIG.debugMode && key) {
                    console.log(`🔄 (调试) 去除重复课程: ${key}`);
                }
                return false;
            }
            seen.add(key);
            return true;
        });
    }
};

    // 进度追踪器
    class ProgressTracker {
        constructor() {
            this.lastVideoProgress = 0;
            this.lastLearningProgress = 0;
            this.stuckCount = 0;
            this.cachedVideoElement = null;
        }
        
        // 统一的视频元素获取方法,带缓存优化
        getVideoElement(useCache = true) {
            if (useCache && this.cachedVideoElement && this.cachedVideoElement.isConnected) {
                return this.cachedVideoElement;
            }
            
        // 优化:使用配置化的选择器
        const video = document.querySelector(CONFIG.selectors.videoPlayer);
            if (video) {
                this.cachedVideoElement = video;
            }
            return video;
        }
        
        getVideoProgress() {
            const video = this.getVideoElement();
            if (!video) return null;
            
            return {
                currentTime: video.currentTime,
                duration: video.duration,
                percentage: video.duration ? (video.currentTime / video.duration * 100) : 0
            };
        }
        
        getLearningProgress() {
        // 优化:使用配置化的选择器
        const progressElement = document.querySelector(CONFIG.selectors.progressCircle);
            if (!progressElement) return null;
            
            const ariaValue = parseInt(progressElement.getAttribute('aria-valuenow'));
        const textElement = progressElement.querySelector(CONFIG.selectors.progressText);
            const textValue = textElement ? textElement.textContent.trim() : '';
            
            return {
                ariaValue: ariaValue || 0,
                textValue,
                isComplete: ariaValue >= 100
            };
        }
        
        checkProgressSync() {
            const videoProgress = this.getVideoProgress();
            const learningProgress = this.getLearningProgress();
            
            if (!videoProgress || !learningProgress) {
                return { synced: false, reason: 'Progress elements not found' };
            }
            
            const progressDiff = Math.abs(videoProgress.percentage - learningProgress.ariaValue);
            const synced = progressDiff < 5; // 允许5%的误差
            
            return {
                synced,
                videoProgress: videoProgress.percentage,
                learningProgress: learningProgress.ariaValue,
                difference: progressDiff
            };
        }
          isProgressStuck() {
            const currentProgress = this.getLearningProgress();
            if (!currentProgress) return false;
            
            if (currentProgress.ariaValue === this.lastLearningProgress) {
                this.stuckCount++;
            } else {
                this.stuckCount = 0;
                this.lastLearningProgress = currentProgress.ariaValue;
            }
            
            return this.stuckCount > 3; // 连续3次检查进度未变化
        }
        
        // 保存视频进度(增强版进度保存)
        saveProgress(currentTime, duration, progressPercentage) {
            try {
                // 基于视频事件的进度保存,不干扰原生机制
                if (!currentTime || !duration || isNaN(currentTime) || isNaN(duration)) {
                    return false;
                }
                  // 更新内部状态
                this.lastVideoProgress = progressPercentage;
                
                // 可选:保存到localStorage作为备份
                const progressData = {
                    currentTime,
                    duration,
                    percentage: progressPercentage,
                    timestamp: Date.now(),
                    courseId: this.getCurrentCourseId()
                };
                
                try {
                    localStorage.setItem('videoProgress', JSON.stringify(progressData));
                } catch (storageError) {
                    // localStorage可能不可用,忽略错误
                }
                
                return true;
            } catch (error) {
                console.warn('⚠️ 进度保存出错:', error);
                return false;
            }
        }
        
        // 获取当前课程ID的辅助方法
        getCurrentCourseId() {
            // 从URL中提取课程ID
            const urlMatch = window.location.href.match(/coursePlayer[^'"]*([\w-]{24,})/i) || 
                            window.location.href.match(/study[^'"]*([\w-]{24,})/i) ||
                            window.location.href.match(/id=([^&]+)/i);
            
            if (urlMatch) {
                return urlMatch[1];
            }
            
            // 从页面元素中提取
            const courseElement = document.querySelector('[data-course-id], [data-id]');
            if (courseElement) {
                return courseElement.getAttribute('data-course-id') || 
                       courseElement.getAttribute('data-id');
            }
            
            // 备用方案:使用页面标题生成ID
            const title = document.title;
            let hash = 0;
            for (let i = 0; i < title.length; i++) {
                const char = title.charCodeAt(i);
                hash = ((hash << 5) - hash) + char;
                hash = hash & hash;
            }
            return `page-${Math.abs(hash).toString(16).substr(0, 16)}`;
        }
    }    // 课程列表页面处理器
    class CourseListHandler {
        constructor() {
            this.courses = [];
            this.currentIndex = 0;
            this.courseNavigator = new CourseNavigator(); // 添加课程导航器实例
            this.setupMessageListener();
    }      // 设置消息监听器,接收来自课程播放页的完成信号
        setupMessageListener() {
            // 防止重复设置监听器
            if (window.courseCompletionListenerSet) {
                console.log('👂 课程完成消息监听器已存在,跳过重复设置');
                return;
            }
        
              window.addEventListener('message', async (event) => {
                if (event.data && event.data.type === 'COURSE_COMPLETED') {
                    console.log('📬 收到课程完成信号:', event.data);
                    
                    const completedCourseName = event.data.courseName;
                    
                    // 记录当前时间,防止重复处理相同时间戳的消息
                    const messageTimestamp = event.data.timestamp;
                    const lastProcessed = window.lastProcessedTimestamp || 0;
                    
                    if (messageTimestamp === lastProcessed) {
                        console.log('⏭️ 跳过重复的课程完成消息 (相同时间戳)');
                        return;
                    }
                    
                    window.lastProcessedTimestamp = messageTimestamp;
                    console.log(`⏰ 处理课程完成消息: ${completedCourseName}`);
                
                      // 确保课程状态已更新为完成
                    if (completedCourseName) {
                        courseStatusManager.markCourseCompleted(completedCourseName);
                        
                    // 错误修复:移除了对不存在的 updateCourseListUIStatus 方法的调用
                    // UI将会在 continueNextCourse 方法中被正确刷新
                    }
                
                      // 等待一下确保页面状态稳定
                await new Promise(resolve => setTimeout(resolve, 1000));
                
                // 更新统计数据
                UIBuilder.updateCourseStats();
                
                      // 继续学习下一个未完成的课程
                    await this.continueNextCourse();
                }
            });
            
            window.courseCompletionListenerSet = true;
            console.log('👂 课程列表页消息监听器已设置');
        }        // 继续学习下一个未完成的课程(优化版 - 避免重复查找)
        async continueNextCourse() {
            console.log('🔄 查找下一个未完成的课程...');
            
            try {
                // 优化:使用缓存的课程列表,避免重复查找DOM
                let courses = this.cachedCourses;
                
                // 只有在缓存不存在或过期时才重新获取
                if (!courses || this.shouldRefreshCourseCache()) {
                    console.log('🔄 刷新课程缓存...');
                    courses = await this.getAllCoursesWithStatus();
                this.cachedCourses = courses; // 更新缓存
                    this.cacheTimestamp = Date.now();
                } else {
                    console.log('📋 使用缓存的课程列表');
                    // 只更新课程状态,不重新查找DOM
                    courses = this.updateCachedCourseStatuses(courses);
                this.cachedCourses = courses; // 状态更新后,同样更新缓存
                }
                
            // BUG修复:不再重新创建UI,而是更新UI
                this.updateCourseListUI(courses);
            
            // 更新统计数据
            UIBuilder.updateCourseStats();
                
                // 筛选出未完成的课程
                const uncompletedCourses = courses.filter(course => !course.isCompleted);
                
                if (uncompletedCourses.length === 0) {
                    console.log('🎉 所有课程都已完成!');
                    this.showCompletionMessage();
                    return;
                }
                
                console.log(`📚 还有 ${uncompletedCourses.length} 个课程需要学习`);
                
                // 开始学习第一个未完成的课程
                const nextCourse = uncompletedCourses[0];
                console.log(`🎯 开始学习下一个课程: ${nextCourse.name}`);
                
                await this.startCourse(nextCourse);
                
            } catch (error) {
                console.error('❌ 继续下一个课程时出错:', error);
            }
        }        // 检查是否需要刷新课程缓存 - 优化缓存策略
        shouldRefreshCourseCache() {
            const CACHE_DURATION = 60000; // 延长缓存时间到60秒,减少重复查找
            
            // 如果没有缓存时间戳,需要刷新
            if (!this.cacheTimestamp) {
                return true;
            }
            
            // 如果超过缓存时间,需要刷新
            if (Date.now() - this.cacheTimestamp > CACHE_DURATION) {
                console.log('🔄 缓存已过期,需要刷新');
                return true;
            }
            
            // 如果没有缓存数据,需要刷新
            if (!this.cachedCourses || this.cachedCourses.length === 0) {
                console.log('🔄 缓存数据为空,需要刷新');
                return true;
            }
            
            return false;
        }

        // 更新缓存中的课程状态(不重新查找DOM)- 优化版
        updateCachedCourseStatuses(courses) {
            if (!courses || courses.length === 0) {
                console.log('⚠️ 无课程数据需要更新状态');
                return [];
            }
            
            console.log(`🔄 更新 ${courses.length} 个课程的缓存状态`);
            
            return courses.map(course => {
                const status = courseStatusManager.getCourseStatus(course.name);
                const updatedCourse = {
                    ...course,
                    status: status ? status.status : 'not_started',
                    isCompleted: courseStatusManager.isCourseCompleted(course.name)
                };
                
                // 只在状态变化时记录日志
                if (course.status !== updatedCourse.status) {
                    console.log(`📝 课程状态变化: ${course.name} (${course.status} -> ${updatedCourse.status})`);
                }
                
                return updatedCourse;
            });
        }

        // 主要的课程列表处理方法
        async handleCourseList() {
            console.log('📚 开始处理课程列表页面...');
            
            // 等待页面加载
            await this.waitForPageLoad();
            
            // 获取所有课程并记录状态
            const courses = await this.getAllCoursesWithStatus();
        this.cachedCourses = courses; // 首次获取时缓存课程列表
        this.cacheTimestamp = Date.now(); // 记录缓存时间
            
            if (courses.length === 0) {
                console.log('❌ 未找到可学习的课程');
            this.showUsageInstructions();
                return;
            }

            // 显示课程状态统计
            this.showCourseStatistics(courses);
            
        // 创建课程列表页UI
        this.listUI = UIBuilder.createUniversalUI({
            pageType: 'list',
            courses: courses,
            onStartLearning: () => this.startAutoLearning(courses),
            onReset: () => {
                if (confirm('确定要重置所有课程的学习状态吗?这将无法撤销。')) {
                    courseStatusManager.clearAllStatuses();
                    alert('课程状态已重置。请刷新页面以应用更改。');
                    location.reload();
                }
            },
            onHelp: () => {
                const modal = UIBuilder.createModal(`
                    <div style="padding: 20px; text-align: left; line-height: 1.8;">
                        <h3 style="text-align: center; margin-bottom: 15px;">📚 课程列表页使用说明</h3>
                        <p><strong>核心功能:</strong></p>
                        <ul>
                            <li>✅ 自动检测并展示所有课程。</li>
                            <li>✅ 一键启动,自动学习所有未完成的课程。</li>
                            <li>✅ 学习完成后自动切换到下一个课程。</li>
                            <li>✅ 实时统计学习进度。</li>
                        </ul>
                        <p><strong>操作指南:</strong></p>
                        <ul>
                            <li>点击 <strong>开始学习</strong> 按钮,脚本将自动为您导航和播放。</li>
                            <li>使用顶部 <strong>收起/展开</strong> 按钮来最小化或恢复面板。</li>
                            <li>如果需要重置所有记录,请点击 <strong>重置</strong> 按钮。</li>
                        </ul>
                    </div>
                `, { modalStyle: { maxWidth: '450px' } });
                document.body.appendChild(modal);
            }
        });
            
            // 如果启用自动学习,开始处理课程
            if (CONFIG.autoSwitchCourse) {
                await this.startAutoLearning(courses);
            }
        // 关键:在UI创建后,立即更新统计数据
        UIBuilder.updateCourseStats();
    }

    // 获取所有课程链接(带重试机制)
    async getAllCourses() {
        console.log('🔍 开始查找课程(带重试机制)...');
        
        const maxRetries = 5;
        const retryDelay = 2000;
        
        for (let attempt = 1; attempt <= maxRetries; attempt++) {
            console.log(`🔄 尝试 ${attempt}/${maxRetries}`);
            
            const courses = SharedUtils.findCourseElements();
            
            if (courses.length > 0) {
                console.log(`✅ 找到 ${courses.length} 个课程!`);
                return courses;
            }
            
            if (attempt < maxRetries) {
                console.log(`⏰ 等待 ${retryDelay}ms 后重试...`);
                await new Promise(resolve => setTimeout(resolve, retryDelay));
            }
        }
        
        console.log('❌ 重试次数用尽,仍未找到课程');
        return [];
        }

        // 获取所有课程并记录状态
        async getAllCoursesWithStatus() {
            console.log('🔍 开始查找课程并记录状态...');
            
            const courses = await this.getAllCourses();
            const coursesWithStatus = [];
            
            for (const course of courses) {
                const courseName = this.extractCourseName(course);
                const status = courseStatusManager.getCourseStatus(courseName);
                
                const courseWithStatus = {
                    ...course,
                    name: courseName,
                    status: status ? status.status : 'not_started',
                    isCompleted: courseStatusManager.isCourseCompleted(courseName)
                };
                
                coursesWithStatus.push(courseWithStatus);
                
                // 如果是首次发现的课程,记录为未开始状态
                if (!status) {
                    courseStatusManager.setCourseStatus(courseName, 'not_started');
                }
            }
            
            console.log(`📝 记录了 ${coursesWithStatus.length} 个课程的状态`);
            return coursesWithStatus;
        }

        // 提取课程名称
        extractCourseName(course) {
            if (course.name) return course.name;
            if (course.title) return course.title;
            
            // 从元素中提取标题
            const titleSelectors = [
                '.item-title',
                '.course-title', 
                '.video-title',
                '.lesson-title',
                '.title',
                'h3', 'h4', 'h5'
            ];
            
        const foundTitle = SharedUtils.findTextContent(course.element, titleSelectors);
        if (foundTitle) {
            return foundTitle;
            }
            
            // 最后尝试使用元素的文本内容
            return course.element.textContent.trim().substring(0, 100) || '未知课程';
        }

        // 显示课程状态统计
        showCourseStatistics(courses) {
            const stats = {
                total: courses.length,
                completed: courses.filter(c => c.isCompleted).length,
                inProgress: courses.filter(c => c.status === 'in_progress').length,
                notStarted: courses.filter(c => c.status === 'not_started').length
            };
            
            const completionRate = stats.total > 0 ? (stats.completed / stats.total * 100).toFixed(1) : 0;
            
            console.log(`📊 课程统计: 总计${stats.total}个,已完成${stats.completed}个,进行中${stats.inProgress}个,未开始${stats.notStarted}个,完成率${completionRate}%`);
        }

        // 开始自动学习流程
        async startAutoLearning(courses) {
        // 首先更新一次UI,标记为进行中
        UIBuilder.updateCourseStats();

        this.currentIndex = courses.findIndex(c => !courseStatusManager.isCourseCompleted(this.extractCourseName(c)));
        if (this.currentIndex === -1) {
                console.log('🎉 所有课程都已完成,无需继续学习!');
                this.showCompletionMessage();
                return;
            }
            
        console.log(`📚 准备学习 ${courses.length} 个课程(跳过了 ${this.currentIndex} 个已完成课程)`);
            
            // 开始学习第一个未完成的课程
        await this.startCourse(courses[this.currentIndex]);
        }

        // 开始学习指定课程
        async startCourse(course) {
            console.log(`🎯 准备开始学习课程: ${course.name}`);
            
            // 标记课程为进行中
            courseStatusManager.markCourseInProgress(course.name);
        
        // ★ 新增:在标记后立即更新UI以高亮当前课程
        const allCourses = await this.getAllCoursesWithStatus();
        // this.updateCourseListUI(allCourses);
            
            try {
                if (course.isCatalogueItem) {
                    console.log('📁 点击课程目录条目');
                    course.element.click();
                } else if (course.element.click) {
                    console.log('🔗 点击课程链接');
                    course.element.click();
                } else {
                    console.log('🌐 直接跳转到课程URL');
                    window.location.href = course.href;
                }
            } catch (error) {
                console.error('❌ 点击课程失败:', error);
                if (course.href && !course.href.includes('javascript:')) {
                    window.location.href = course.href;
                }
            }
        }

        // 显示学习完成消息
        showCompletionMessage() {
            const stats = courseStatusManager.getStatistics();
            
            const content = document.createElement('div');
            content.style.textAlign = 'center';
            
            const title = UIBuilder.createTitle('🎉 学习完成!', {
                style: { color: 'var(--aura-success)' }
            });
            content.appendChild(title);
            
            const message = document.createElement('div');
            message.style.cssText = `
                margin: 12px 0;
                color: var(--aura-text-primary);
                line-height: 1.8;
            `;
            message.innerHTML = `
                <div>恭喜您完成了所有课程的学习!</div>
                <div style="margin-top: 10px;">
                    <strong>学习统计:</strong><br>
                    总课程数: ${stats.total}<br>
                    已完成: ${stats.completed}<br>
                    完成率: ${stats.completionRate}%
                </div>
            `;
            content.appendChild(message);
            
            const okBtn = UIBuilder.createButton('确定', {
            style: { background: 'var(--aura-primary)', color: '#ffffff' },
                onClick: () => modal.remove()
            });
            content.appendChild(okBtn);
              const modal = UIBuilder.createModal(content, {
                closable: true,
                closeOnOverlay: false
            });
            
            document.body.appendChild(modal);
        }

        // 显示脚本使用说明
        showUsageInstructions() {
            const content = document.createElement('div');
            const title = UIBuilder.createTitle('📖 使用说明', {
                style: { color: 'var(--aura-text-secondary)' }
            });
            content.appendChild(title);
            const instructions = document.createElement('div');
            instructions.style.cssText = `
                margin: 12px 0;
                color: var(--aura-text-primary);
                line-height: 1.8;
                font-size: 12px;
            `;
            instructions.innerHTML = `
                <div><strong>💡 功能特色:</strong></div>
                <ul style="margin: 10px 0; padding-left: 20px;">
                <li>✅ 自动播放与进度监控</li>
                <li>📊 实时学习统计</li>
                <li>🔄 断点续学与状态保存</li>
                <li>🛡️ 错误处理与重试机制</li>
                </ul>
                <div style="color: var(--aura-warning); margin-top: 15px;">
                <strong>⚠️ 注意事项与局限性:</strong><br>
                • 播放页面必须始终置于前台,切换标签页或最小化浏览器会导致进度暂停或检测不到<br>
                • 本脚本仅供学习研究,风险自负<br>
                • 请勿频繁刷新或批量操作,避免服务器压力<br>
                • 网站更新可能导致脚本失效,建议定期关注更新<br>
                • 使用前请确认符合网站服务条款
                </div>
            `;
            content.appendChild(instructions);
            const okBtn = UIBuilder.createButton('我知道了', {
                style: { 
                background: 'var(--aura-primary)',
                color: '#ffffff',
                    width: '100%',
                    textAlign: 'center'
                },
                onClick: () => modal.remove()
            });
            content.appendChild(okBtn);
            const modal = UIBuilder.createModal(content, {
                closable: true,
                closeOnOverlay: true
            });
            document.body.appendChild(modal);
        }
        
        // 检测是否在课程列表页面
        isCourseListPage() {
            return window.location.href.includes('specialdetail') || 
                   window.location.href.includes('courseList') ||
                   document.querySelector('.course-list, .pd-course-list, .specialdetail');
        }
          // 智能等待页面加载
        async waitForPageLoad(timeout = 30000) {
            console.log('⏳ 等待页面加载完成...');
            
            const startTime = Date.now();
            
            return new Promise((resolve) => {
                const checkInterval = setInterval(() => {
                    // 检查页面是否加载完成的多个条件
                    const isReady = document.readyState === 'complete' &&
                                  document.querySelectorAll('a').length > 0 &&
                                  (document.querySelector('.el-loading-mask') === null);
                    
                    if (isReady || Date.now() - startTime > timeout) {
                        clearInterval(checkInterval);
                        console.log('✅ 页面加载检查完成');
                        resolve(isReady);
                    }
                }, 500);
            });
        }

    // 仅更新课程列表的UI内容,而不重新创建整个面板
        updateCourseListUI(courses) {
        const courseListContainer = document.getElementById('course-list-items-container');
        if (!courseListContainer) {
            console.error('❌ 无法找到课程列表容器进行更新!');
                    return;
                }
                
        // 使用通用UI的渲染方法更新课程列表
        UIBuilder.renderCourseList(courseListContainer, courses);
        }
    }    // 课程导航器
    class CourseNavigator {        constructor(progressTracker = null) {
            this.currentCourseIndex = 0;
            this.progressTracker = progressTracker; // 使用依赖注入
        }
        
        // 使用 ProgressTracker 的视频元素获取方法,避免重复
        getVideoElement(useCache = true) {
            if (this.progressTracker) {
                return this.progressTracker.getVideoElement(useCache);
            }
            
            // 降级方案:直接查找(如果没有 progressTracker)
            return document.querySelector('#emiya-video video');
        }
        
        getCurrentCourse() {
            return document.querySelector('.el-menu-item.is-active');
        }

          getAllCourses() {
        // 调用共享的课程查找逻辑
        const courseInfoArray = SharedUtils.findCourseElements();
        console.log(`🗺️ 导航器找到 ${courseInfoArray.length} 个课程元素`);
        
        // 返回DOM元素列表以保持兼容性
        return courseInfoArray.map(info => info.element);
    }

    getNextCourse() {
            const courses = this.getAllCourses();
            const currentIndex = Array.from(courses).findIndex(course => 
            course.classList.contains('is-active')
        );
            
            return currentIndex < courses.length - 1 ? courses[currentIndex + 1] : null;
        }
    }    // 主要的自动学习播放器
    class AutoLearningPlayer {
        constructor(config = {}) {
            this.config = { ...CONFIG, ...config };
            this.progressTracker = new ProgressTracker();
            this.courseNavigator = new CourseNavigator(this.progressTracker); // 注入依赖
            this.isRunning = false;
            this.checkCount = 0;
            this.currentCourseName = null; // 当前课程名称
            this.lastLearningProgress = 0; // 上次记录的学习进度
            this.progressObserver = null; // 学习进度监控器
            
            // 绑定事件处理器
            this.handleVideoEvents = this.handleVideoEvents.bind(this);
            this.handleProgressUpdate = this.handleProgressUpdate.bind(this);
            
            // 设置全局引用,供页面可见性处理使用
            window.autoLearningPlayer = this;
            
            // 设置页面可见性事件监听器
            this.setupVisibilityEventListeners();
            
            // 初始化UI
            this.initUI();
        }

        // 设置页面可见性事件监听器
        setupVisibilityEventListeners() {
            // 监听进度保存事件
            document.addEventListener('saveProgress', (event) => {
                const isSilent = event.detail && event.detail.silent;
                if (!isSilent) {
                this.addLog(`收到进度保存请求: ${event.detail.reason}`);
                }
                this.saveCurrentProgress();
            });

            // 监听状态检查事件
            document.addEventListener('checkStatus', (event) => {
                const isSilent = event.detail && event.detail.silent;
                if (!isSilent) {
                this.addLog(`收到状态检查请求: ${event.detail.reason}`);
                }
                this.checkCurrentStatus();
            });

            // 监听进度检查事件
            document.addEventListener('checkProgress', (event) => {
                const isSilent = event.detail && event.detail.silent;
                if (!isSilent) {
                this.addLog(`收到进度检查请求: ${event.detail.reason}`);
                }
                this.checkCourseProgress();
            });
        }

        // 保存当前进度
        saveCurrentProgress() {
            try {
                const video = this.getVideoElement();
                if (video) {
                    const currentTime = video.currentTime;
                    const duration = video.duration;
                    const progressPercentage = duration > 0 ? (currentTime / duration) * 100 : 0;
                    
                    this.progressTracker.saveProgress(currentTime, duration, progressPercentage);
                    // 静默保存,不输出日志
                }
            } catch (error) {
                // 静默处理错误
            }
        }

        // 检查当前状态
        checkCurrentStatus() {
            try {
                const video = this.getVideoElement();
                if (video) {
                    const isPlaying = !video.paused;
                    const currentTime = video.currentTime;
                    const duration = video.duration;
                    const progress = duration > 0 ? (currentTime / duration) * 100 : 0;
                    
                    // 如果视频暂停了,尝试恢复播放
                    if (!isPlaying && progress < 100) {
                        video.play().catch(() => {
                            // 静默处理错误
                        });
                    }
                }
            } catch (error) {
                // 静默处理错误
            }
        }

        initUI() {
        if (this.config.showConsoleLog) {
            // 获取课程列表用于显示
            const courseElements = SharedUtils.findCourseElements();
            const courses = courseElements.map(courseInfo => {
                return {
                    name: courseInfo.name, // 修复:使用 courseInfo.name 而不是 courseInfo.title
                    href: courseInfo.href,
                    isCompleted: courseStatusManager.isCourseCompleted(courseInfo.name), // 修复:使用 courseInfo.name
                    status: courseStatusManager.getCourseStatus(courseInfo.name)?.status || 'not_started' // 修复:使用 courseInfo.name
                };
            });

            // 使用通用UI组件替代原有的播放页UI
            this.playerUI = UIBuilder.createUniversalUI({
                pageType: 'player',
                onReset: () => {
                    if (confirm('确定要重置所有课程的学习状态吗?这将无法撤销。')) {
                        courseStatusManager.clearAllStatuses();
                        alert('课程状态已重置。请刷新页面以应用更改。');
                        location.reload();
                    }
                },
                onHelp: () => {
                    const modal = UIBuilder.createModal(`
                        <div style="padding: 20px; text-align: left; line-height: 1.8;">
                            <h3 style="text-align: center; margin-bottom: 15px;">🎬 播放页使用说明</h3>
                            <p><strong>核心功能:</strong></p>
                            <ul>
                                <li>▶️ 自动播放和暂停视频。</li>
                                <li>📊 实时监控学习进度并显示在日志中。</li>
                                <li>🔄 课程完成后自动跳转到下一个。</li>
                                <li>🛡️ 拦截烦人的“离开页面”弹窗。</li>
                            </ul>
                            <p><strong>注意事项:</strong></p>
                            <ul>
                                <li>⚠️ 为了保证脚本正常运行,请勿手动操作播放器。</li>
                                <li>📺 请将此页面保持在前台,切换标签页可能导致学习暂停。</li>
                            </ul>
                        </div>
                    `, { modalStyle: { maxWidth: '450px' } });
                    document.body.appendChild(modal);
                }
            });
        }
        this.addLog(`脚本启动 v${GM_info.script.version}`, 'SUCCESS');
            this.detectAndLogCourseName();
        }

        // 检测并记录课程名称
        detectAndLogCourseName() {
            const courseName = this.getCurrentCourseName();
        if (courseName) {
             this.addLog(`当前课程: ${courseName}`);
            } else {
             this.addLog('正在等待课程名称加载...', 'INFO');
        }
            return courseName;
    }

    // 设置学习进度监控
        setupLearningProgressMonitor() {
            // 等待页面加载完成后再设置监控
            setTimeout(() => {
                const progressElement = document.querySelector('.el-progress--circle[aria-valuenow]');
                if (progressElement) {
                this.addLog('找到学习进度组件,开始监控', 'INFO');
                    
                    // 创建监控器
                    this.progressObserver = new MutationObserver((mutations) => {
                        mutations.forEach((mutation) => {
                            if (mutation.type === 'attributes' && mutation.attributeName === 'aria-valuenow') {
                                const newProgress = parseInt(progressElement.getAttribute('aria-valuenow')) || 0;
                                this.handleLearningProgressUpdate(newProgress);
                            }
                        });
                    });
                    
                    // 开始监控
                    this.progressObserver.observe(progressElement, {
                        attributes: true,
                        attributeFilter: ['aria-valuenow']
                    });
                    
                    // 记录初始进度并检查是否已完成
                    const initialProgress = parseInt(progressElement.getAttribute('aria-valuenow')) || 0;
                this.addLog(`初始学习进度: ${initialProgress}%`);
                    this.lastLearningProgress = initialProgress;
                    
                    // 关键修复:如果初始进度就是100%,立即触发完成处理
                    if (initialProgress >= 100) {
                    this.addLog('发现课程已完成!', 'SUCCESS');
                        setTimeout(() => {
                            this.handleCourseCompletion();
                        }, 1000);
                    }
                } else {
                this.addLog('未找到学习进度组件', 'WARNING');
                }
            }, 2000);
        }

        // 处理学习进度更新
        handleLearningProgressUpdate(newProgress) {
            if (this.lastLearningProgress !== newProgress) {
            this.addLog(`学习进度更新: ${this.lastLearningProgress}% → ${newProgress}%`);
                this.lastLearningProgress = newProgress;
                
                // 检查是否完成
                if (newProgress >= 100) {
                this.addLog('课程学习完成!', 'SUCCESS');
                this.handleCourseCompletion(); // 直接调用,不再使用 setTimeout
                }
            }
        }        // 处理课程完成 - 唯一标准:学习进度100%
        async handleCourseCompletion() {
        // 立即停止所有监控器,防止重复触发
        if (this.progressObserver) {
            this.progressObserver.disconnect();
            this.addLog('学习进度监控器已停止', 'INFO');
        }

            const courseName = this.getCurrentCourseName();
        this.addLog(`课程已完成: ${courseName}`, 'SUCCESS');
              // 记录课程完成状态
        if (courseName && courseStatusManager) {
            courseStatusManager.markCourseCompleted(courseName);
            this.addLog(`已标记课程完成状态: ${courseName}`);
            
            // 关键:立即更新UI上的统计数据
            UIBuilder.updateCourseStats();
        }

        // 等待指定的延迟时间,以确保服务器完全保存进度
        this.addLog(`等待 ${this.config.completionDelay / 1000} 秒,以确保最终进度已上报...`);
        await this.sleep(this.config.completionDelay);
            
            // 如果启用自动切换,切换到下一个课程;否则关闭页面
            if (this.config.autoSwitchCourse) {
            this.addLog('准备切换到下一个课程...');
                await this.switchToNextCourse();
            } else {
            this.addLog('准备关闭页面...', 'INFO');
                window.close();
            }
        }

    addLog(message, type = 'INFO') {
        // 总是输出到控制台(用于调试)
        console.log(`[${type}] ${message}`);
        // 根据showConsoleLog配置决定是否显示UI日志
        if (this.config.showConsoleLog) {
            UIBuilder.addLogEntry(message, type);
    }        }
        getVideoElement() {
            return this.courseNavigator.getVideoElement();
        }        // 获取当前课程名称 - 课程名称是识别课程的唯一ID
        getCurrentCourseName() {
            if (this.currentCourseName) {
                return this.currentCourseName;
            }

            // 优先级顺序的课程名称提取策略
            const extractionStrategies = [
                // 策略1:专用课程标题选择器
                () => {
                    const selectors = [
                        '.course-title',
                        '.video-title', 
                        '.lesson-title',
                        '.course-name',
                        '.content-title'
                    ];
                return SharedUtils.findTextContent(document, selectors);
                },
                
                // 策略2:通用标题选择器
                () => {
                    const selectors = ['h1', 'h2', '.title'];
                const foundTitle = SharedUtils.findTextContent(document, selectors);
                if (foundTitle && !foundTitle.includes('中国干部网络学院')) {
                    return foundTitle;
                    }
                    return null;
                },
                
                // 策略3:面包屑导航
                () => {
                    const breadcrumb = document.querySelector('.breadcrumb .active, .page-title');
                    if (breadcrumb && breadcrumb.textContent.trim()) {
                        return breadcrumb.textContent.trim();
                    }
                    return null;
                },
                
                // 策略4:页面标题
                () => {
                    if (document.title && 
                        document.title !== '中国干部网络学院' && 
                        !document.title.includes('登录')) {
                        return document.title.replace(' - 中国干部网络学院', '').trim();
                    }
                    return null;
                },
                
                // 策略5:从URL提取课程ID作为备用标识
                () => {
                    const urlMatch = window.location.href.match(/coursePlayer[^'"]*([\w-]{24,})/i) || 
                                    window.location.href.match(/id=([^&]+)/i);
                    
                    if (urlMatch) {
                        return `课程-${urlMatch[1]}`;
                    }
                    return null;
                }
            ];

            // 按优先级尝试提取课程名称
            for (const strategy of extractionStrategies) {
                try {
                    const courseName = strategy();
                    if (courseName) {
                        this.currentCourseName = courseName;
                    this.addLog(`识别到课程名称: ${courseName}`, 'INFO');
                        return this.currentCourseName;
                    }
                } catch (error) {
                    console.warn('课程名称提取策略失败:', error);
                }
            }

            // 如果所有策略都失败,使用时间戳作为唯一标识
            const fallbackName = `未知课程-${Date.now()}`;
            this.currentCourseName = fallbackName;
        this.addLog(`无法识别课程名称,使用备用标识: ${fallbackName}`, 'WARNING');
            return this.currentCourseName;
        }

    async start() {
        if (this.isRunning) {
            this.addLog('脚本已在运行中', 'WARNING');
            return;
        }

            this.isRunning = true;
            
            // 获取并记录当前课程名称
            const courseName = this.getCurrentCourseName();
            
            // ⚠️ 重要:先检查课程是否已经完成,避免重复学习
            if (courseStatusManager.isCourseCompleted(courseName)) {
            this.addLog(`课程已完成,跳过学习: ${courseName}`, 'SUCCESS');
                
                if (this.config.autoSwitchCourse) {
                this.addLog('准备切换到下一个未完成的课程...');
                    await this.sleep(3000);
                    await this.switchToNextCourse();
                } else {
                this.addLog('课程已完成,准备关闭页面...');
                    await this.sleep(2000);
                    window.close();
                }
                return;
            }
            
        this.addLog(`开始学习课程: ${courseName}`, 'INFO');
            // 标记课程为进行中
            courseStatusManager.markCourseInProgress(courseName);

            try {
                // 等待视频元素加载
                const video = await this.waitForVideo();
                if (!video) {
                this.addLog('未找到视频元素,启动进度监控以处理非视频课程', 'WARNING');
                // 即使没有视频,也要启动进度监控来处理非视频课程
                this.setupLearningProgressMonitor();
                    return;
                }

                // 设置视频事件监听
                this.setupVideoEvents(video);
                
            // 启动学习进度监控 (MutationObserver)
            this.setupLearningProgressMonitor();
                
                // 开始主循环
                await this.mainLoop();
                
            } catch (error) {
            this.addLog(`运行错误: ${error.message}`, 'ERROR');
                console.error('AutoLearningPlayer error:', error);
            } finally {
                this.isRunning = false;
        }
        }

        // 工具函数:等待指定时间
        sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

        async waitForVideo() {
        this.addLog('等待视频加载...', 'INFO');
            
            for (let i = 0; i < 30; i++) {
                const video = this.getVideoElement();
                if (video) {
                this.addLog('视频元素已找到', 'SUCCESS');
                    return video;
                }
                await this.sleep(1000);
            }
            
            return null;
        }        setupVideoEvents(video) {
            // 移除之前的事件监听器(如果存在)
            video.removeEventListener('loadedmetadata', this.handleVideoEvents);
            video.removeEventListener('timeupdate', this.handleProgressUpdate);
            video.removeEventListener('ended', this.handleVideoEvents);
            video.removeEventListener('error', this.handleVideoEvents);

            // 添加新的事件监听器
            video.addEventListener('loadedmetadata', this.handleVideoEvents);
            video.addEventListener('timeupdate', this.handleProgressUpdate);
            video.addEventListener('ended', this.handleVideoEvents);  
        video.addEventListener('error', this.handleVideoEvents);            this.addLog('视频事件监听器已设置', 'INFO');
        }

        handleVideoEvents(event) {
            const video = event.target;
            
            switch (event.type) {
                case 'loadedmetadata':
                this.addLog(`视频元数据加载完成: ${Math.round(video.duration)}秒`);
                    break;
                    
                case 'ended':
                this.addLog('视频播放结束', 'SUCCESS');
                    this.handleVideoEnd();
                    break;
                    
                case 'error':
                this.addLog(`视频播放错误: ${video.error?.message || '未知错误'}`, 'ERROR');
                    break;            }
        }

        handleProgressUpdate(event) {
            const video = event.target;
            
            if (video.duration > 0) {
                const progress = (video.currentTime / video.duration) * 100;
                
                // 保存进度(但不记录日志,避免与学习进度混淆)
                if (this.config.enhancedProgressSave) {
                    this.progressTracker.saveProgress(video.currentTime, video.duration, progress);
                }                // 注意:课程完成判断仅依据页面显示的学习进度,不依据视频播放进度
            }
        }

        async handleVideoEnd() {
        this.addLog('视频播放完成', 'SUCCESS');
            
            // 重置完成检查标记
            this.videoCompletionChecked = false;
            
            // 注意:课程完成判断已由学习进度监控器自动处理
            // 不再基于视频播放完成来判断课程是否完成
        this.addLog('视频播放结束,等待学习进度达到100%完成课程', 'INFO');
        }        async switchToNextCourse() {
            try {
            this.addLog('准备切换到下一个课程...', 'INFO');
                
                const courseName = this.getCurrentCourseName();
            this.addLog(`当前完成的课程: ${courseName}`);
                  // 发送课程完成消息给课程列表页面
                const completionMessage = {
                    type: 'COURSE_COMPLETED',
                    courseName: courseName,
                    timestamp: Date.now()
                };
                
            this.addLog('发送课程完成消息给课程列表页面', 'INFO');
                
                // 尝试发送消息给可能的父页面或开启者页面
                if (window.opener && !window.opener.closed) {
                    // 如果是通过window.open打开的,发送给开启者
                    window.opener.postMessage(completionMessage, '*');
                this.addLog('消息已发送给开启者页面', 'SUCCESS');
                } else if (window.parent !== window) {
                    // 如果是在iframe中,发送给父页面
                    window.parent.postMessage(completionMessage, '*');
                this.addLog('消息已发送给父页面', 'SUCCESS');
                } else {
                    // 发送给所有可能的窗口
                    window.postMessage(completionMessage, '*');
                this.addLog('消息已发送到当前窗口', 'INFO');
                }
                  // 等待一下确保消息发送完成
                await this.sleep(2000);
                
            this.addLog('课程完成,准备关闭页面...', 'INFO');
                
                // 尝试关闭页面
            this.addLog('执行页面关闭', 'INFO');
                window.close();
                
                // 如果关闭失败,使用备用策略
                setTimeout(() => {
                    if (!window.closed) {
                    this.addLog('第一次关闭失败,使用备用策略', 'WARNING');
                        this.handleCloseFailure();
                    }
                }, 1000);
                
                return true;
                  } catch (error) {
            this.addLog(`切换课程失败: ${error.message}`, 'ERROR');
                console.error('Switch course error:', error);
                  // 出错时也尝试关闭页面
            this.addLog('出错时尝试关闭页面', 'INFO');
                
                // 设置浏览器弹窗处理器 - 已被新的拦截机制取代,故删除
                // this.setupBrowserDialogHandler();
                
                setTimeout(() => {
                    window.close();
                    
                    // 如果关闭失败,使用备用策略
                    setTimeout(() => {
                        if (!window.closed) {
                        this.addLog('错误处理中关闭失败,使用智能返回', 'WARNING');
                            this.handleCloseFailure();
                        }
                    }, 1000);
                }, 1000);
                  return false;
            }
        }
        
        // 处理关闭失败的情况
        handleCloseFailure() {
        this.addLog('处理关闭失败,检查备用策略', 'INFO');
            
            // 优先尝试返回到父页面
            if (window.opener && !window.opener.closed) {
            this.addLog('返回到开启者页面', 'INFO');
                window.opener.focus();
                window.close();
            } else if (window.history.length > 1) {
            this.addLog('使用历史记录返回', 'INFO');
                window.history.back();
            } else {
                // 最后才考虑重新导航
            this.addLog('导航回列表页', 'INFO');
                const listUrl = sessionStorage.getItem('courseListUrl') || 
                              document.referrer ||
                              window.location.href.replace(/coursePlayer.*/, 'specialdetail');
                
                // 添加标记防止重复打开
                if (!sessionStorage.getItem('courseCompletionRedirecting')) {
                    sessionStorage.setItem('courseCompletionRedirecting', 'true');
                    window.location.href = listUrl;
                }
            }
        }

        getCurrentCourseId() {
        // 统一调用 progressTracker 中的方法,避免代码重复
        return this.progressTracker.getCurrentCourseId();
        }

        async mainLoop() {
        this.addLog('开始主循环', 'INFO');
            
            while (this.isRunning) {
                try {
                    const video = this.getVideoElement();
                    
                    if (!video) {
                    this.addLog('视频元素丢失,尝试重新获取', 'WARNING');
                        await this.sleep(this.config.checkInterval);
                        continue;
                }
                
                // 检查视频状态并进行相应操作
                    await this.processVideo(video);
                    
                } catch (error) {
                this.addLog(`主循环错误: ${error.message}`, 'ERROR');
                    console.error('Main loop error:', error);
                }
                
            // 定期等待,但不再检查超时
                await this.sleep(this.config.checkInterval);
            }
        }

        async processVideo(video) {
            // 确保视频静音(如果配置要求)
            if (this.config.enforceGlobalMute && !video.muted) {
                video.muted = true;
            this.addLog('视频已静音', 'INFO');
            }

            // 检查视频是否暂停,如果是则播放
            if (video.paused && this.config.autoPlay) {
                try {
                    await video.play();
                this.addLog('视频开始播放', 'INFO');
                } catch (error) {
                this.addLog(`视频播放失败: ${error.message}`, 'ERROR');
                }
            }

            // 检查播放速度
            if (video.playbackRate !== 1) {
                video.playbackRate = 1;
            this.addLog('播放速度已重置为正常', 'INFO');  
            }        }

        sleep(ms) {
            // 如果启用随机延迟,添加随机成分
            if (this.config.enableRandomDelay) {
                const randomDelay = Math.random() * (this.config.maxDelay - this.config.minDelay) + this.config.minDelay;
                ms += randomDelay;
            }
            
            return new Promise(resolve => setTimeout(resolve, ms));
        }

        stop() {
            this.isRunning = false;
        this.addLog('自动学习已停止', 'INFO');
        }
    }

    // 页面类型检测和主函数
    function getPageType() {
        const url = window.location.href;
        const hash = window.location.hash;
        
    console.log('🔍 开始检测页面类型...');
        
    // 1. 优先通过URL特征判断
        if (url.includes('coursePlayer') || hash.includes('coursePlayer')) {
        console.log('📺 检测为视频播放页 (基于URL)');
            return 'video';
        }
        
        if (url.includes('courseList') || hash.includes('courseList') || 
            url.includes('specialdetail') || hash.includes('specialdetail') ||
            url.includes('pdchanel') || hash.includes('pdchanel')) {
        console.log('📚 检测为课程列表页 (基于URL)');
            return 'courseList';
        }
        
    // 2. 如果URL不明确,通过DOM特征判断
    console.log('...URL不明确,继续通过DOM特征检测');

            // 检查视频元素
            const video = document.querySelector('#emiya-video video, video');
            if (video) {
        console.log('📺 检测为视频播放页 (基于DOM)');
                return 'video';
            }
            
            // 检查课程列表元素
    const courseList = document.querySelector('.catalogue_item, .course-item, .specialdetail_catalogue, .course-list, .pd-course-list');
            if (courseList) {
        console.log('📚 检测为课程列表页 (基于DOM)');
                return 'courseList';
            }
            
    console.log('❓ 未能识别页面类型');
        return 'unknown';
    }

    // 全局监听器设置标记 - 防止重复设置
    let globalMessageListenerSet = false;
    let urlChangeListenerSet = false;
    let isMainRunning = false; // 防止main函数重复执行
    let mainCallCount = 0; // 添加调用计数器
    const MAX_MAIN_CALLS = 5; // 最大调用次数限制
    let lastMainCallTime = 0; // 最后一次调用时间
    let scriptStopped = false; // 脚本停止标记

    // 创建全局课程状态管理器
    const courseStatusManager = new CourseStatusManager();

    async function main() {
    // 在开始时确保清除所有旧的UI
    const existingPlayerUI = document.getElementById('auto-learning-player-ui');
    if (existingPlayerUI) existingPlayerUI.remove();
    const existingListUI = document.getElementById('auto-learn-ui-container');
    if (existingListUI) existingListUI.remove();

    console.log('🚀 Main function started');
    const pageType = getPageType();

    try {
        console.log('🚀 中国干部网络学院自动学习脚本启动 v2.18.1 - UI/UX优化版');
        console.log('🔧 配置:', CONFIG);
        
        // 优化:注入样式表
        injectStyles();
            
            // 等待页面加载完成
            if (document.readyState !== 'complete') {
                await new Promise(resolve => {
                    window.addEventListener('load', resolve);
                });
            }
            
            // 额外等待,确保动态内容加载
        await new Promise(resolve => setTimeout(resolve, 3000));            console.log(`📄 当前页面类型: ${pageType}`);
            
            switch (pageType) {
                case 'video':
                    console.log('🎬 初始化视频播放器...');
                    const player = new AutoLearningPlayer();
                    await player.start();
                    break;
                case 'courseList':
                    console.log('📚 初始化课程列表处理器...');
                    const courseListHandler = new CourseListHandler();
                    
                    // 保存当前页面URL,用于后续返回
                    sessionStorage.setItem('courseListUrl', window.location.href);
                    
                    await courseListHandler.handleCourseList();                    break;
                case 'unknown':
                default:
                    console.log('❓ 未知页面类型,使用降级策略');
                    
                    // 等待更长时间后重新检测
                    setTimeout(async () => {
                        const video = document.querySelector('#emiya-video video, video');
                        const courseList = document.querySelector('.catalogue_item, .course-item, .specialdetail_catalogue');
                        
                        if (video) {
                            console.log('🎬 降级检测:发现视频元素,启动播放器');
                            const player = new AutoLearningPlayer();
                            await player.start();
                        } else if (courseList) {
                            console.log('📚 降级检测:发现课程列表,启动列表处理器');
                            const courseListHandler = new CourseListHandler();
                            await courseListHandler.handleCourseList();
                        } else {
                            console.log('❌ 降级检测也未找到可处理的元素');
                        }
                    }, 5000);
                    break;
            }
        } catch (error) {
            console.error('❌ 主函数执行错误:', error);
        } finally {
            isMainRunning = false; // 确保标记被重置
        console.log(`✅ main函数执行完成。`);
        }
        
        // 只在第一次运行时设置URL变化监听器,防止重复设置
        if (!urlChangeListenerSet) {
            setupUrlChangeListener();
            urlChangeListenerSet = true;
        }
        
        console.log('📡 脚本初始化完成');
    console.log(`🏁 Main function finished for page type: ${pageType}`);
    }

    // 单独的URL变化监听器设置函数
    function setupUrlChangeListener() {
    let debounceTimer;

    // 创建一个"防抖"函数,确保main只在URL稳定后执行一次
    const debouncedMain = () => {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(() => {
            console.log('🚀 Executing debounced main function after URL change.');
            main();
        }, 500); // 500ms的防抖延迟
    };

    let oldHref = document.location.href;
    const body = document.querySelector("body");
    const observer = new MutationObserver(mutations => {
        if (oldHref !== document.location.href) {
            oldHref = document.location.href;
            console.log(`🌀 URL change detected (MutationObserver) to: ${oldHref}.`);
            debouncedMain();
        }
    });
    observer.observe(body, { childList: true, subtree: true });

    // 备用方案:监听hashchange事件
    window.addEventListener('hashchange', () => {
        console.log('🌀 Hash change detected (hashchange event).');
        debouncedMain();
    });
    console.log('👂 URL change listener is active.');
}

// --- 脚本启动点 ---

// 启动URL变化监听器
setupUrlChangeListener();

// 首次运行主函数
main();
})();