Greasy Fork

Greasy Fork is available in English.

国家开放大学实验学院自动刷课脚本

自动识别并处理Moodle平台的学习项目,包括视频自动播放、文档自动处理等

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         国家开放大学实验学院自动刷课脚本
// @namespace    https://github.com/lucky845/ouchn-course-brusher-script
// @version      1.2.1
// @description  自动识别并处理Moodle平台的学习项目,包括视频自动播放、文档自动处理等
// @author       lucky845
// @match        https://moodle.syxy.ouchn.cn/mod/*
// @grant        none
// @run-at       document-idle
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // 防止页面刷新时重复执行
    let initialized = false;
    
    // 脚本运行状态
    let scriptEnabled = true;
    
    // localStorage键名
    const STORAGE_KEY_ENABLED = 'ouchn_brusher_enabled';
    const STORAGE_KEY_POSITION = 'ouchn_brusher_position';
    
    // 从localStorage读取脚本开关状态
    function loadScriptEnabled() {
        const saved = localStorage.getItem(STORAGE_KEY_ENABLED);
        if (saved !== null) {
            return saved === 'true';
        }
        return true;
    }
    
    // 保存脚本开关状态到localStorage
    function saveScriptEnabled(enabled) {
        localStorage.setItem(STORAGE_KEY_ENABLED, enabled.toString());
    }
    
    // 从localStorage读取悬浮窗位置(百分比)
    function loadPanelPosition() {
        const saved = localStorage.getItem(STORAGE_KEY_POSITION);
        if (saved) {
            try {
                return JSON.parse(saved);
            } catch (e) {
                return null;
            }
        }
        return null;
    }
    
    // 保存悬浮窗位置到localStorage(百分比)
    function savePanelPosition(x, y) {
        // 转换为百分比
        var percentX = (x / window.innerWidth) * 100;
        var percentY = (y / window.innerHeight) * 100;
        localStorage.setItem(STORAGE_KEY_POSITION, JSON.stringify({ x: percentX, y: percentY }));
    }
    
    // 重置悬浮窗位置
    function resetPanelPosition() {
        localStorage.removeItem(STORAGE_KEY_POSITION);
    }
    
    // 创建悬浮控制窗口
    function createControlPanel() {
        // 检查是否已存在控制窗口
        if (document.getElementById('ouchn-brusher-container')) {
            return;
        }
        
        // 读取保存的开关状态
        scriptEnabled = loadScriptEnabled();
        
        // 创建容器
        const container = document.createElement('div');
        container.id = 'ouchn-brusher-container';
        
        // 读取保存的位置
        const savedPos = loadPanelPosition();
        let initialX = window.innerWidth - 60; // 默认在右边缘
        let initialY = 100; // 默认在顶部下方100px
        
        if (savedPos) {
            // 检查保存的位置是否合理(百分比值应该在0-100之间)
            if (savedPos.x >= 0 && savedPos.x <= 100 &&
                savedPos.y >= 0 && savedPos.y <= 100) {
                initialX = savedPos.x + '%';
                initialY = savedPos.y + '%';
            } else {
                // 如果位置不合理,重置位置
                resetPanelPosition();
            }
        }
        
        // 判断是否为百分比值
        const isPercentX = typeof initialX === 'string' && initialX.endsWith('%');
        const isPercentY = typeof initialY === 'string' && initialY.endsWith('%');
        
        container.style.cssText = `
            position: fixed;
            left: ${initialX}${isPercentX ? '' : 'px'};
            top: ${initialY}${isPercentY ? '' : 'px'};
            z-index: 999999;
            font-family: Arial, sans-serif;
            transition: all 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
            transform-origin: top left;
        `;
        
        // 创建小圆球按钮(用于缩放状态)
        const button = document.createElement('div');
        button.id = 'ouchn-brusher-button';
        button.style.cssText = `
            width: 50px;
            height: 50px;
            background: #4CAF50;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
            color: white;
            font-size: 24px;
            z-index: 999999;
            position: relative;
        `;
        button.textContent = '📚'; // 书籍图标
        
        // 创建控制窗口
        const panel = document.createElement('div');
        panel.id = 'ouchn-brusher-panel';
        panel.style.cssText = `
            position: absolute;
            top: 0;
            right: 60px; /* 默认位于按钮左侧 */
            width: 280px;
            background: #ffffff;
            border: 1px solid #e0e0e0;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            font-size: 14px;
            display: none;
            z-index: 999998;
            padding: 10px;
        `;
        
        // 创建标题栏
        const header = document.createElement('div');
        header.style.cssText = `
            padding: 12px;
            background: #4CAF50;
            color: white;
            border-radius: 8px 8px 0 0;
            font-weight: bold;
            display: flex;
            justify-content: space-between;
            align-items: center;
            cursor: move;
        `;
        header.innerHTML = `
            <span>刷课脚本控制</span>
            <button id="ouchn-brusher-close" style="
                background: none;
                border: none;
                color: white;
                cursor: pointer;
                font-size: 16px;
                padding: 0;
                width: 20px;
                height: 20px;
                display: flex;
                align-items: center;
                justify-content: center;
            ">×</button>
        `;
        
        // 创建内容区域
        const content = document.createElement('div');
        content.style.cssText = `
            padding: 12px;
        `;
        
        // 创建启用/禁用开关
        const toggleDiv = document.createElement('div');
        toggleDiv.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        `;
        toggleDiv.innerHTML = `
            <span>启用刷课脚本</span>
            <label class="switch">
                <input type="checkbox" id="ouchn-brusher-toggle" ${scriptEnabled ? 'checked' : ''}>
                <span class="slider round"></span>
            </label>
        `;
        
        // 创建状态显示
        const statusDiv = document.createElement('div');
        statusDiv.id = 'ouchn-brusher-status';
        statusDiv.style.cssText = `
            padding: 8px;
            background: #f5f5f5;
            border-radius: 4px;
            margin-bottom: 15px;
            font-size: 12px;
            color: #666;
        `;
        statusDiv.textContent = scriptEnabled ? '脚本已启用,等待页面加载...' : '脚本已禁用';
        
        // 创建操作按钮
        const buttonsDiv = document.createElement('div');
        buttonsDiv.style.cssText = `
            display: flex;
            gap: 8px;
        `;
        
        const startButton = document.createElement('button');
        startButton.id = 'ouchn-brusher-start';
        startButton.textContent = '开始刷课';
        startButton.style.cssText = `
            flex: 1;
            padding: 8px 12px;
            background: #4CAF50;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
        `;
        
        const stopButton = document.createElement('button');
        stopButton.id = 'ouchn-brusher-stop';
        stopButton.textContent = '停止刷课';
        stopButton.style.cssText = `
            flex: 1;
            padding: 8px 12px;
            background: #f44336;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
        `;
        
        // 组装控制窗口
        buttonsDiv.appendChild(startButton);
        buttonsDiv.appendChild(stopButton);
        content.appendChild(toggleDiv);
        content.appendChild(statusDiv);
        content.appendChild(buttonsDiv);
        panel.appendChild(header);
        panel.appendChild(content);
        
        // 组装容器
        container.appendChild(button);
        container.appendChild(panel);
        
        // 添加到页面
        document.body.appendChild(container);
        
        // 添加样式
        const style = document.createElement('style');
        style.textContent = `
            .switch {
                position: relative;
                display: inline-block;
                width: 44px;
                height: 24px;
            }
            
            .switch input {
                opacity: 0;
                width: 0;
                height: 0;
            }
            
            .slider {
                position: absolute;
                cursor: pointer;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background-color: #ccc;
                transition: .4s;
            }
            
            .slider:before {
                position: absolute;
                content: "";
                height: 18px;
                width: 18px;
                left: 3px;
                bottom: 3px;
                background-color: white;
                transition: .4s;
            }
            
            input:checked + .slider {
                background-color: #4CAF50;
            }
            
            input:focus + .slider {
                box-shadow: 0 0 1px #4CAF50;
            }
            
            input:checked + .slider:before {
                transform: translateX(20px);
            }
            
            .slider.round {
                border-radius: 24px;
            }
            
            .slider.round:before {
                border-radius: 50%;
            }
            
            #ouchn-brusher-container {
                transition: all 0.3s ease;
            }
            
            #ouchn-brusher-container.dragging {
                opacity: 0.8;
                transition: none;
            }
            
            #ouchn-brusher-container.dragging #ouchn-brusher-button {
                cursor: grabbing;
            }
        `;
        document.head.appendChild(style);
        
        // 展开/收起面板
        let isPanelOpen = false; // 默认关闭
        // 初始状态为可见(不最小化)
        // 移除默认的minimized类,让用户能看到悬浮窗
        // container.classList.add('minimized');
        
        button.onclick = function(e) {
            e.stopPropagation(); // 防止事件冒泡
            // 只有当不是拖拽状态时才切换面板
            if (!isActuallyDragging) {
                if (isPanelOpen) {
                    panel.style.display = 'none';
                    isPanelOpen = false;
                } else {
                    // 根据悬浮窗位置动态调整面板位置
                    var rect = container.getBoundingClientRect();
                    var windowWidth = document.documentElement.clientWidth;
                    var centerX = windowWidth / 2;
                    
                    if (rect.left < centerX) {
                        // 在左侧,面板显示在按钮右侧
                        panel.style.right = 'auto';
                        panel.style.left = '60px';
                    } else {
                        // 在右侧,面板显示在按钮左侧
                        panel.style.left = 'auto';
                        panel.style.right = '60px';
                    }
                    
                    panel.style.display = 'block';
                    isPanelOpen = true;
                }
            }
        };
        
        // 点击面板外部只关闭面板(不改变最小化状态)
        document.addEventListener('click', function(event) {
            if (!container.contains(event.target)) {
                if (isPanelOpen) {
                    panel.style.display = 'none';
                    isPanelOpen = false;
                }
            }
        });
        
        // 防止面板内部点击导致关闭
        panel.addEventListener('click', function(e) {
            e.stopPropagation();
        });
        
        // 添加事件监听器
        document.getElementById('ouchn-brusher-close').onclick = function(e) {
            e.stopPropagation();
            panel.style.display = 'none';
            isPanelOpen = false;
        };
        
        // 更新按钮状态
        function updateButtonStates() {
            const startButton = document.getElementById('ouchn-brusher-start');
            const stopButton = document.getElementById('ouchn-brusher-stop');
            
            if (scriptEnabled) {
                startButton.disabled = true;
                startButton.style.opacity = '0.5';
                startButton.style.cursor = 'not-allowed';
                stopButton.disabled = false;
                stopButton.style.opacity = '1';
                stopButton.style.cursor = 'pointer';
            } else {
                startButton.disabled = false;
                startButton.style.opacity = '1';
                startButton.style.cursor = 'pointer';
                stopButton.disabled = true;
                stopButton.style.opacity = '0.5';
                stopButton.style.cursor = 'not-allowed';
            }
        }
        
        // 初始化按钮状态
        updateButtonStates();
        
        document.getElementById('ouchn-brusher-toggle').onchange = function() {
            scriptEnabled = this.checked;
            saveScriptEnabled(scriptEnabled); // 保存状态
            const status = document.getElementById('ouchn-brusher-status');
            if (scriptEnabled) {
                status.textContent = '脚本已启用,等待页面加载...';
                status.style.background = '#f5f5f5';
                status.style.color = '#666';
            } else {
                status.textContent = '脚本已禁用';
                status.style.background = '#ffebee';
                status.style.color = '#c62828';
            }
            // 更新按钮状态
            updateButtonStates();
        };
        
        document.getElementById('ouchn-brusher-start').onclick = function() {
            scriptEnabled = true;
            saveScriptEnabled(true); // 保存状态
            document.getElementById('ouchn-brusher-toggle').checked = true;
            const status = document.getElementById('ouchn-brusher-status');
            status.textContent = '开始刷课...';
            status.style.background = '#e8f5e8';
            status.style.color = '#2e7d32';
            
            // 更新按钮状态
            updateButtonStates();
            
            // 重新初始化脚本
            initialized = false;
            init();
        };
        
        document.getElementById('ouchn-brusher-stop').onclick = function() {
            scriptEnabled = false;
            saveScriptEnabled(false); // 保存状态
            document.getElementById('ouchn-brusher-toggle').checked = false;
            const status = document.getElementById('ouchn-brusher-status');
            status.textContent = '脚本已停止';
            status.style.background = '#ffebee';
            status.style.color = '#c62828';
            
            // 更新按钮状态
            updateButtonStates();
        };
        
        // 拖拽功能 - 简化版
        var dragOffsetX = 0;
        var dragOffsetY = 0;
        var hideTimer = null;
        
        // 鼠标悬停事件处理
        container.addEventListener('mouseenter', function() {
            if (hideTimer) {
                clearTimeout(hideTimer);
                hideTimer = null;
            }
            // 鼠标靠近时显示完整浮窗并恢复透明度
            container.style.transition = 'all 0.3s ease';
            container.style.transform = 'translateX(0)';
            container.style.opacity = '1';
        });
        
        // 鼠标离开时开始隐藏计时器
        container.addEventListener('mouseleave', function() {
            // 鼠标离开后,开始隐藏计时器,0.5秒后才隐藏
            hideTimer = setTimeout(function() {
                // 只降低透明度,不缩入侧边,确保悬浮窗始终可见
                container.style.transition = 'opacity 0.3s ease';
                container.style.transform = 'translateX(0)'; // 重置transform
                container.style.opacity = '0.6';
            }, 500);
        });
        
        // 为按钮和标题栏添加拖拽事件
        var startX, startY;
        var isActuallyDragging = false;
        
        function startDrag(e) {
            container.style.transition = 'none'; // 拖拽时禁用动画
            
            var clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
            var clientY = e.type.includes('touch') ? e.touches[0].clientY : e.clientY;
            
            startX = clientX;
            startY = clientY;
            isActuallyDragging = false;
            
            var rect = container.getBoundingClientRect();
            dragOffsetX = clientX - rect.left;
            dragOffsetY = clientY - rect.top;
            
            if (hideTimer) {
                clearTimeout(hideTimer);
                hideTimer = null;
            }
            
            // 显示完整浮窗
            container.style.transform = 'translateX(0)';
            container.style.opacity = '1';
            
            e.preventDefault();
        }
        
        function doDrag(e) {
            // 确保只处理鼠标或触摸事件
            if (!e.clientX && !e.touches) return;
            
            var clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
            var clientY = e.type.includes('touch') ? e.touches[0].clientY : e.clientY;
            
            // 检查是否真正开始拖拽(移动超过5像素)
            if (!isActuallyDragging) {
                var distance = Math.sqrt(Math.pow(clientX - startX, 2) + Math.pow(clientY - startY, 2));
                if (distance > 5) {
                    isActuallyDragging = true;
                } else {
                    return;
                }
            }
            
            var newX = clientX - dragOffsetX;
            var newY = clientY - dragOffsetY;
            
            // 限制在视口内,确保不会超出屏幕边缘
            // 使用实际可视区域大小,以适应控制台的存在
            var containerWidth = container.offsetWidth;
            var containerHeight = container.offsetHeight;
            var windowWidth = document.documentElement.clientWidth;
            var windowHeight = document.documentElement.clientHeight;
            var maxX = windowWidth - containerWidth;
            var maxY = windowHeight - containerHeight;
            
            // 确保坐标在有效范围内
            newX = Math.max(0, Math.min(newX, maxX));
            newY = Math.max(0, Math.min(newY, maxY));
            
            container.style.left = newX + 'px';
            container.style.top = newY + 'px';
            
            e.preventDefault();
        }
        
        function endDrag() {
            if (isActuallyDragging) {
                container.style.transition = 'all 0.3s ease'; // 恢复动画
                
                // 保存位置
                var rect = container.getBoundingClientRect();
                savePanelPosition(rect.left, rect.top);
                
                // 自动吸附到最近的边缘(只有在靠近边缘时才吸附)
                // 使用requestAnimationFrame优化性能
                requestAnimationFrame(snapToEdge);
            }
            isActuallyDragging = false;
        }
        
        // 物理磁吸系统
        function snapToEdge() {
            var rect = container.getBoundingClientRect();
            // 使用实际可视区域大小,而不是整个屏幕尺寸,以适应控制台的存在
            var windowWidth = document.documentElement.clientWidth;
            var windowHeight = document.documentElement.clientHeight;
            var containerWidth = container.offsetWidth;
            var containerHeight = container.offsetHeight;
            
            // 吸附阈值(像素)
            var snapThreshold = 80;
            
            // 计算距离各边缘的距离
            var distanceToLeft = rect.left;
            var distanceToRight = windowWidth - rect.right;
            var distanceToTop = rect.top;
            var distanceToBottom = windowHeight - rect.bottom;
            
            // 检查是否靠近任何边缘
            var isNearEdge = distanceToLeft < snapThreshold || distanceToRight < snapThreshold || 
                           distanceToTop < snapThreshold || distanceToBottom < snapThreshold;
            
            if (isNearEdge) {
                var targetX = parseInt(container.style.left) || 0;
                var targetY = parseInt(container.style.top) || 0;
                
                // 水平吸附逻辑
                if (distanceToLeft < snapThreshold) {
                    // 吸附到左边缘,但保持完全可见
                    targetX = 0;
                } else if (distanceToRight < snapThreshold) {
                    // 吸附到右边缘,但保持完全可见
                    targetX = windowWidth - containerWidth;
                }
                
                // 垂直吸附逻辑
                if (distanceToTop < snapThreshold) {
                    // 吸附到上边缘,但保持完全可见
                    targetY = 0;
                } else if (distanceToBottom < snapThreshold) {
                    // 吸附到下边缘,但保持完全可见
                    targetY = windowHeight - containerHeight;
                }
                
                // 确保容器完全在视口内
                targetX = Math.max(0, Math.min(targetX, windowWidth - containerWidth));
                targetY = Math.max(0, Math.min(targetY, windowHeight - containerHeight));
                
                // 应用平滑过渡
                container.style.transition = 'left 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94), top 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)';
                container.style.left = targetX + 'px';
                container.style.top = targetY + 'px';
                container.style.opacity = '1'; // 吸附时保持完全可见
                
                // 保存吸附后的位置
                setTimeout(function() {
                    var newRect = container.getBoundingClientRect();
                    savePanelPosition(newRect.left, newRect.top);
                }, 200);
            } else {
                // 非靠近边缘时,只降低透明度
                container.style.transition = 'opacity 0.3s ease';
                container.style.opacity = '0.6';
            }
        }
        
        // 拖拽事件处理函数
        function setupDragEvents() {
            // 开始拖拽时添加移动和结束事件监听器
            function startDragWithEvents(e) {
                startDrag(e);
                
                // 添加移动事件监听器
                document.addEventListener('mousemove', doDrag);
                document.addEventListener('touchmove', doDrag, { passive: false });
                
                // 添加结束事件监听器
                function endDragWithCleanup(e) {
                    endDrag(e);
                    
                    // 移除事件监听器
                    document.removeEventListener('mousemove', doDrag);
                    document.removeEventListener('touchmove', doDrag);
                    document.removeEventListener('mouseup', endDragWithCleanup);
                    document.removeEventListener('touchend', endDragWithCleanup);
                    document.removeEventListener('mouseleave', endDragWithCleanup);
                    document.removeEventListener('touchcancel', endDragWithCleanup);
                }
                
                document.addEventListener('mouseup', endDragWithCleanup);
                document.addEventListener('touchend', endDragWithCleanup);
                document.addEventListener('mouseleave', endDragWithCleanup);
                document.addEventListener('touchcancel', endDragWithCleanup);
            }
            
            // 为按钮和标题栏添加开始拖拽事件
            button.addEventListener('mousedown', startDragWithEvents);
            button.addEventListener('touchstart', startDragWithEvents, { passive: false });
            header.addEventListener('mousedown', startDragWithEvents);
            header.addEventListener('touchstart', startDragWithEvents, { passive: false });
        }
        
        // 初始化拖拽事件
        setupDragEvents();
        
        // 点击面板外部关闭面板
        document.addEventListener('click', function(e) {
            if (!container.contains(e.target)) {
                panel.style.display = 'none';
            }
        });
        
        // 初始化状态
        // 从localStorage加载状态
        var savedEnabled = localStorage.getItem(STORAGE_KEY_ENABLED);
        if (savedEnabled !== null) {
            scriptEnabled = savedEnabled === 'true';
            document.getElementById('ouchn-brusher-toggle').checked = scriptEnabled;
        }
        
        // 加载保存的位置
        var loadedPos = loadPanelPosition();
        if (loadedPos) {
            container.style.left = loadedPos.x + '%';
            container.style.top = loadedPos.y + '%';
        }
        
        // 监听屏幕缩放事件,自动调整位置
        window.addEventListener('resize', function() {
            var currentLeft = parseFloat(container.style.left);
            var currentTop = parseFloat(container.style.top);
            
            // 如果是百分比已经设置好了,不需要调整
            // 如果是旧版本的像素值,需要转换为百分比
            if (container.style.left.indexOf('px') !== -1) {
                var newLeft = (currentLeft / window.innerWidth) * 100;
                var newTop = (currentTop / window.innerHeight) * 100;
                container.style.left = newLeft + '%';
                container.style.top = newTop + '%';
            }
        });
        
        // 初始状态为完全可见
        container.style.transform = 'translateX(0)';
        container.style.opacity = '1';
        
        // 确保容器在初始化时可见
        container.style.display = 'block';
    }
    
    // 更新状态信息
    function updateStatus(message, type = 'info') {
        const status = document.getElementById('ouchn-brusher-status');
        if (status) {
            status.textContent = message;
            
            switch (type) {
                case 'success':
                    status.style.background = '#e8f5e8';
                    status.style.color = '#2e7d32';
                    break;
                case 'error':
                    status.style.background = '#ffebee';
                    status.style.color = '#c62828';
                    break;
                case 'warning':
                    status.style.background = '#fff3e0';
                    status.style.color = '#ef6c00';
                    break;
                default:
                    status.style.background = '#f5f5f5';
                    status.style.color = '#666';
            }
        }
    }

    // 脚本初始化
    function init() {
        // 创建控制面板
        createControlPanel();
        
        // 检查脚本是否启用
        if (!scriptEnabled) {
            updateStatus('脚本已禁用', 'error');
            return;
        }
        
        if (initialized) {
            return;
        }
        initialized = true;
        updateStatus('脚本已启动,开始检查页面...', 'success');
        
        // 检查当前平台
        if (window.location.hostname === 'moodle.syxy.ouchn.cn') {
            updateStatus('检测到Moodle平台', 'info');
            setTimeout(() => {
                if (window.location.pathname.includes('/mod/')) {
                    // 在Moodle学习项目页面
                    updateStatus('当前页面是课程学习项目页面,开始处理...', 'info');
                    processMoodleLearningItem();
                }
            }, 2000);
        }
    }

    // 检查视频状态并自动播放
    function checkVideoStatus() {
        // 尝试多种选择器查找视频元素
        let videoElement = document.querySelector('video');
        if (!videoElement) {
            // 尝试查找iframe中的视频
            const iframe = document.querySelector('iframe');
            if (iframe) {
                try {
                    const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                    videoElement = iframeDoc.querySelector('video');
                } catch (e) {
                    // 忽略错误
                }
            }
        }
        
        if (videoElement) {
            // 确保视频已开始播放
            if (videoElement.paused) {
                try {
                    videoElement.play();
                } catch (e) {
                    // 忽略错误
                }
            }
            
            // 监听视频结束事件
            videoElement.addEventListener('ended', function() {
                // 等待页面更新后再处理下一个项目
                setTimeout(() => {
                    // 对于Moodle平台,返回课程页面并处理下一个项目
                    window.history.back();
                    setTimeout(() => {
                        processMoodleCourse();
                    }, 2000);
                }, 2000);
            });
            
            // 定期检查视频状态,确保视频在播放
            const videoCheckInterval = setInterval(() => {
                if (videoElement.paused && !videoElement.ended) {
                    try {
                        videoElement.play();
                    } catch (e) {
                        // 忽略错误
                    }
                } else if (videoElement.ended) {
                    clearInterval(videoCheckInterval);
                    setTimeout(() => {
                        // 对于Moodle平台,返回课程页面并处理下一个项目
                        window.history.back();
                        setTimeout(() => {
                            processMoodleCourse();
                        }, 2000);
                    }, 2000);
                }
            }, 10000); // 每10秒检查一次
        } else {
            // 检查是否为文档、网页内容或文件页面等
            const contentElements = document.querySelectorAll('.document-viewer, .pdf-viewer, .text-content, .resourcecontent, .mod-resource-content, .forum, .mod-forum-content, .page-content, .mod-page-content, .content');
            
            if (contentElements.length > 0) {
                // 对于网页内容或文件页面,等待5秒后继续
                setTimeout(() => {
                    // 对于Moodle平台,返回课程页面并处理下一个项目
                    window.history.back();
                    setTimeout(() => {
                        processMoodleCourse();
                    }, 2000);
                }, 5000);
            } else {
                // 对于其他类型,等待3秒后继续
                setTimeout(() => {
                    // 对于Moodle平台,返回课程页面并处理下一个项目
                    window.history.back();
                    setTimeout(() => {
                        processMoodleCourse();
                    }, 2000);
                }, 3000);
            }
        }
    }

    // 暂停脚本函数
    function pauseScript() {
        scriptEnabled = false;
        saveScriptEnabled(false);
        updateStatus('所有学习项目已完成,脚本已自动暂停', 'success');
        
        // 更新UI状态
        const toggle = document.getElementById('ouchn-brusher-toggle');
        if (toggle) {
            toggle.checked = false;
        }
        
        const startButton = document.getElementById('ouchn-brusher-start');
        const stopButton = document.getElementById('ouchn-brusher-stop');
        if (startButton && stopButton) {
            startButton.disabled = false;
            startButton.style.opacity = '1';
            startButton.style.cursor = 'pointer';
            stopButton.disabled = true;
            stopButton.style.opacity = '0.5';
            stopButton.style.cursor = 'not-allowed';
        }
    }
    
    // 处理Moodle平台的课程详情页
    function processMoodleCourse() {
        // 查找课程内容区域
        const courseContent = document.querySelector('.course-content, .topics, .newgk-coursecontent');
        if (!courseContent) {
            return;
        }
        
        // 查找所有学习项目
        // 根据HTML结构,学习项目可能在.section或其他容器中
        const learningItems = courseContent.querySelectorAll('.activity, .resource, .modtype_resource, .modtype_url, .modtype_video, .section .activityinstance');
        
        // 需要用户手动操作的项目类型
        const manualActionTypes = [
            'forum', // 论坛/发帖
            'assign', // 作业
            'quiz', // 测验/答题
            'survey', // 调查
            'feedback', // 反馈
            'choice', // 选择
            'database', // 数据库
            'workshop' // 工作坊
        ];
        
        let hasUncompletedItems = false;
        
        // 遍历学习项目,找到未完成的项目
        for (const item of learningItems) {
            // 检查项目是否已完成
            let isCompleted = false;
            
            // 方法1:检查完成状态元素
            const completionElement = item.querySelector('.completion-icon, .completionstate, .status');
            if (completionElement) {
                const completionClass = completionElement.className;
                const completionText = completionElement.textContent || completionElement.innerText;
                if (completionClass.includes('completed') || completionClass.includes('state-completed') || 
                    completionText.includes('已完成') || completionText.includes('完成')) {
                    isCompleted = true;
                }
            }
            
            // 方法2:检查项目是否有完成标记
            const completedMark = item.querySelector('.icon-check, .completion-complete, .completion-check');
            if (completedMark) {
                isCompleted = true;
            }
            
            if (!isCompleted) {
                // 检查项目类型,判断是否需要用户手动操作
                let requiresManualAction = false;
                const itemClass = item.className;
                const itemLink = item.querySelector('a');
                const itemHref = itemLink ? itemLink.href : '';
                
                // 检查项目类名和链接是否包含需要手动操作的类型
                for (const type of manualActionTypes) {
                    if (itemClass.includes(type) || itemHref.includes(`/mod/${type}/`)) {
                        requiresManualAction = true;
                        break;
                    }
                }
                
                if (!requiresManualAction) {
                    hasUncompletedItems = true;
                    // 查找项目链接
                    let link = item.querySelector('a');
                    if (!link) {
                        // 尝试查找父元素中的链接
                        link = item.closest('.activityinstance')?.querySelector('a');
                    }
                    if (link) {
                        link.click();
                        return;
                    }
                }
            }
        }
        
        // 如果没有未完成的项目,暂停脚本
        if (!hasUncompletedItems) {
            pauseScript();
        }
    }

    // 处理Moodle平台的学习项目页面
    function processMoodleLearningItem() {
        // 检查是否为视频类型
        const videoElement = document.querySelector('video');
        if (videoElement) {
            // 尝试自动播放视频(使用静音模式绕过Chrome的自动播放限制)
            function tryPlayVideo() {
                // 设置视频为静音,这样可以绕过Chrome的自动播放限制
                videoElement.muted = true;
                
                if (videoElement.paused) {
                    try {
                        videoElement.play();
                    } catch (e) {
                        // 5秒后继续,即使视频未播放
                        setTimeout(() => {
                            findNextItemInSidebar();
                        }, 5000);
                    }
                }
            }
            
            // 尝试自动播放
            tryPlayVideo();
            
            // 监听用户交互,当用户有任何触发时,取消静音
            document.addEventListener('click', function enableSound() {
                if (videoElement.muted) {
                    videoElement.muted = false;
                }
                // 只需要监听一次
                document.removeEventListener('click', enableSound);
            });
            
            // 也监听其他可能的用户交互事件
            document.addEventListener('keydown', function enableSound() {
                if (videoElement.muted) {
                    videoElement.muted = false;
                }
                // 只需要监听一次
                document.removeEventListener('keydown', enableSound);
            });
            
            // 监听视频结束事件
            videoElement.addEventListener('ended', function() {
                // 尝试在侧边栏找到下一个未完成的项目
                setTimeout(() => {
                    findNextItemInSidebar();
                }, 2000);
            });
            
            // 定期检查视频状态,确保视频在播放
            const videoCheckInterval = setInterval(() => {
                if (videoElement.paused && !videoElement.ended) {
                    try {
                        videoElement.play();
                    } catch (e) {
                        // 忽略错误
                    }
                } else if (videoElement.ended) {
                    clearInterval(videoCheckInterval);
                    setTimeout(() => {
                        findNextItemInSidebar();
                    }, 2000);
                }
            }, 10000); // 每10秒检查一次
        } else {
            // 检查是否为网页内容、文件页面或论坛等
            // 增加更多选择器以匹配不同类型的页面
            const contentElements = document.querySelectorAll(
                '.resourcecontent, .mod-resource-content, .forum, .mod-forum-content, .page-content, .mod-page-content, .content, ' +
                '#page-content, .main-content, .region-content, .course-content, .forum-content, .discussion-content'
            );
            
            // 检查页面URL是否包含特定路径,以识别不同类型的页面
            const isForumPage = window.location.pathname.includes('/mod/forum/');
            const isResourcePage = window.location.pathname.includes('/mod/resource/');
            const isPagePage = window.location.pathname.includes('/mod/page/');
            
            // 如果找到内容元素或通过URL识别为特定类型的页面
            if (contentElements.length > 0 || isForumPage || isResourcePage || isPagePage) {
                // 对于网页内容或文件页面,等待5秒后继续
                setTimeout(() => {
                    // 尝试在侧边栏找到下一个未完成的项目
                    findNextItemInSidebar();
                }, 5000);
            } else {
                // 对于其他类型,等待3秒后继续
                setTimeout(() => {
                    // 尝试在侧边栏找到下一个未完成的项目
                    findNextItemInSidebar();
                }, 3000);
            }
        }
    }

    // 在侧边栏中寻找下一个未完成的学习项目
    function findNextItemInSidebar() {
        // 尝试查找侧边栏容器
        const sidebar = document.querySelector('#nav-drawer, .sidebar, .nav-sidebar');
        if (!sidebar) {
            // 尝试返回课程页面
            if (document.referrer && document.referrer.includes('/course/view.php')) {
                window.location.href = document.referrer;
            } else {
                // 如果没有referrer,尝试从URL中提取课程ID并构建课程页面URL
                const courseIdMatch = window.location.search.match(/id=(\d+)/);
                if (courseIdMatch) {
                    const courseId = courseIdMatch[1];
                    const courseUrl = `https://moodle.syxy.ouchn.cn/course/view.php?id=${courseId}`;
                    window.location.href = courseUrl;
                } else {
                    // 否则使用history.back()
                    window.history.back();
                }
            }
            setTimeout(() => {
                processMoodleCourse();
            }, 2000);
            return;
        }
        
        // 查找侧边栏中的所有学习项目链接
        // 按单元组织学习项目为二维数组
        const sidebarStructure = []; // 二维数组:[单元][学习项目]
        const seenUrls = new Set(); // 用于去重
        const sections = sidebar.querySelectorAll('.section');
        
        // 遍历每个单元,收集学习项目
        sections.forEach((section, sectionIndex) => {
            // 查找单元中的学习项目
            const activities = section.querySelectorAll('.activity, .resource, .modtype_resource, .modtype_url, .modtype_video, .modtype_quiz');
            
            const sectionItems = [];
            activities.forEach((activity) => {
                const link = activity.querySelector('a');
                if (link && link.href.includes('/mod/')) {
                    // 去重:只添加未见过的链接
                    if (!seenUrls.has(link.href)) {
                        seenUrls.add(link.href);
                        sectionItems.push(link);
                    }
                }
            });
            
            if (sectionItems.length > 0) {
                sidebarStructure.push(sectionItems);
            }
        });
        
        // 将二维数组扁平化为一维数组,方便处理
        const sidebarItems = sidebarStructure.flat();
        
        // 如果没有通过单元找到项目,尝试直接查找所有学习项目链接
        if (sidebarItems.length === 0) {
            const allLinks = sidebar.querySelectorAll('a');
            for (const link of allLinks) {
                const href = link.href;
                if (href.includes('/mod/') && !seenUrls.has(href)) {
                    seenUrls.add(href);
                    sidebarItems.push(link);
                }
            }
        }
        
        if (sidebarItems.length === 0) {
            // 尝试返回课程页面
            if (document.referrer && document.referrer.includes('/course/view.php')) {
                window.location.href = document.referrer;
            } else {
                // 如果没有referrer,尝试从URL中提取课程ID并构建课程页面URL
                const courseIdMatch = window.location.search.match(/id=(\d+)/);
                if (courseIdMatch) {
                    const courseId = courseIdMatch[1];
                    const courseUrl = `https://moodle.syxy.ouchn.cn/course/view.php?id=${courseId}`;
                    window.location.href = courseUrl;
                } else {
                    // 否则使用history.back()
                    window.history.back();
                }
            }
            setTimeout(() => {
                processMoodleCourse();
            }, 2000);
            return;
        }
        
        // 找到当前页面在侧边栏中的位置
        let currentIndex = -1;
        const currentUrl = window.location.href;
        const currentUrlPath = window.location.pathname;
        const currentUrlId = currentUrl.split('id=')[1]?.split('&')[0];
        
        // 方法1:通过完整URL匹配
        for (let i = 0; i < sidebarItems.length; i++) {
            const item = sidebarItems[i];
            const itemUrl = item.href;
            
            if (currentUrl === itemUrl) {
                currentIndex = i;
                break;
            }
        }
        
        // 方法2:通过路径匹配
        if (currentIndex === -1) {
            for (let i = 0; i < sidebarItems.length; i++) {
                const item = sidebarItems[i];
                const itemUrl = item.href;
                const itemPath = new URL(itemUrl).pathname;
                
                if (currentUrlPath === itemPath) {
                    currentIndex = i;
                    break;
                }
            }
        }
        
        // 方法3:通过ID匹配
        if (currentIndex === -1 && currentUrlId) {
            for (let i = 0; i < sidebarItems.length; i++) {
                const item = sidebarItems[i];
                const itemUrl = item.href;
                const itemId = itemUrl.split('id=')[1]?.split('&')[0];
                
                if (currentUrlId === itemId) {
                    currentIndex = i;
                    break;
                }
            }
        }
        
        // 方法4:通过包含关系查找
        if (currentIndex === -1) {
            for (let i = 0; i < sidebarItems.length; i++) {
                const item = sidebarItems[i];
                const itemUrl = item.href;
                
                // 检查当前URL是否包含项目URL的关键部分
                if (currentUrl.includes(itemUrl.split('?')[0].split('/').pop())) {
                    currentIndex = i;
                    break;
                }
            }
        }
        
        // 检查是否是最后一项
        if (currentIndex >= 0 && currentIndex === sidebarItems.length - 1) {
            // 是最后一项,暂停脚本
            pauseScript();
            return;
        }
        
        // 从当前位置的下一个项目开始查找未完成的项目
        if (currentIndex >= 0 && currentIndex < sidebarItems.length - 1) {
            // 从当前位置的下一个项目开始遍历
            for (let i = currentIndex + 1; i < sidebarItems.length; i++) {
                const item = sidebarItems[i];
                const itemUrl = item.href;
                
                // 使用直接跳转而不是点击,避免可能的页面跳转问题
                setTimeout(() => {
                    window.location.href = itemUrl;
                }, 500);
                return;
            }
        }
        
        // 如果没有找到下一个项目,返回课程列表页
        // 尝试返回课程页面
        if (document.referrer && document.referrer.includes('/course/view.php')) {
            window.location.href = document.referrer;
        } else {
            // 如果没有referrer,尝试从URL中提取课程ID并构建课程页面URL
            const courseIdMatch = window.location.search.match(/id=(\d+)/);
            if (courseIdMatch) {
                const courseId = courseIdMatch[1];
                const courseUrl = `https://moodle.syxy.ouchn.cn/course/view.php?id=${courseId}`;
                window.location.href = courseUrl;
            } else {
                // 否则使用history.back()
                window.history.back();
            }
        }
        setTimeout(() => {
            processMoodleCourse();
        }, 2000);
    }

    // 页面加载完成后初始化
    // 使用 DOMContentLoaded 事件,确保页面结构已加载
    window.addEventListener('DOMContentLoaded', function() {
        setTimeout(init, 1000); // 延迟1秒执行,确保页面完全加载
    });
    
    // 监听页面hash变化,处理路由切换
    window.addEventListener('hashchange', function() {
        // 重置初始化状态,以便重新执行
        initialized = false;
        setTimeout(init, 1000); // 延迟1秒执行,确保页面完全加载
    });
    
    // 监听页面加载完成事件,作为后备
    window.addEventListener('load', function() {
        if (!initialized) {
            setTimeout(init, 500); // 延迟500毫秒执行
        }
    });

})();