在线培训助手增强版

党旗飘飘学习助手增强版,支持自动刷课、自动答题,配合AI模型实现智能解答

// ==UserScript==
// @name         在线培训助手增强版
// @namespace    http://tampermonkey.net/
// @version      1.35
// @description  党旗飘飘学习助手增强版,支持自动刷课、自动答题,配合AI模型实现智能解答
// @author       bugo
// @match        *://*/jjfz/play*
// @match        *://*/*/jjfz/play*
// @match        *://*/jjfz/lesson/exam*
// @match        *://*/*/jjfz/lesson/exam*
// @match        *://*/jjfz/exam_center/end_exam*
// @match        *://*/*/jjfz/exam_center/end_exam*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_notification
// @grant        GM_xmlhttpRequest
// @run-at       document-start
// @license      MIT
// @connect      *
// ==/UserScript==

(function() {
    'use strict';
    
    console.log("在线培训助手已加载");
    
    // 检测当前页面类型
    const isExamPage = window.location.href.includes('/lesson/exam') || window.location.href.includes('/exam_center/end_exam');
    const isPlayPage = window.location.href.includes('/jjfz/play');
    
    // 配置信息
    const config = {
        // AI API设置
        ai: {
            apiKey: GM_getValue('apiKey', ''),
            modelUrl: GM_getValue('modelUrl', 'https://deepseek.com/api/v1/chat/completions'),
            modelName: GM_getValue('modelName', 'deepseek-chat'),
            temperature: GM_getValue('temperature', 0.7),
            maxTokens: GM_getValue('maxTokens', 500),
            apiTimeout: 30000 // API请求超时时间(毫秒)
        },
        
        // 课程设置
        course: {
            autoPlay: GM_getValue('autoPlay', true),
            autoNext: true
        },
        
        // UI设置
        ui: {
            panelExpanded: GM_getValue('panelExpanded', true),
            activeTab: GM_getValue('activeTab', isExamPage ? 'exam' : 'course')
        }
    };
    
    // 保存配置
    function saveConfig() {
        try {
            // 保存API配置
            GM_setValue('modelUrl', config.ai.modelUrl);
            GM_setValue('modelName', config.ai.modelName);
            GM_setValue('apiKey', config.ai.apiKey);
            GM_setValue('temperature', config.ai.temperature);
            GM_setValue('maxTokens', config.ai.maxTokens);
            GM_setValue('apiTimeout', config.ai.apiTimeout);
            
            // 保存课程配置
            GM_setValue('autoPlay', config.course.autoPlay);
            
            // 保存UI配置
            GM_setValue('panelExpanded', config.ui.panelExpanded);
            GM_setValue('activeTab', config.ui.activeTab);
            
            // 输出保存配置日志
            console.log("配置已保存");
            return true;
        } catch (error) {
            console.error("保存配置失败:", error);
            return false;
        }
    }
    
    // 工具函数
    const utils = {
        // 获取视频元素
        getVideo: () => document.querySelector("video"),
        
        // 获取资源ID
        getRid: () => {
            const html = document.documentElement.innerHTML;
            const match = html.match(/rid[\s:="']*(\d+)["'\s]/);
            return match ? match[1] : null;
        },
        
        // 获取当前题目信息
        getQuestionInfo: () => {
            try {
                // 获取题目文本
                const questionTitle = document.querySelector('.exam_h2')?.textContent || '';
                
                // 判断题目类型
                let questionType = '';
                if (document.querySelector('.e_cont_title span')?.textContent.includes('单选题')) {
                    questionType = '单选题';
                } else if (document.querySelector('.e_cont_title span')?.textContent.includes('多选题')) {
                    questionType = '多选题';
                } else if (document.querySelector('.e_cont_title span')?.textContent.includes('判断题')) {
                    questionType = '判断题';
                } else if (document.querySelector('.summary_question')) {
                    questionType = '填空题';
                }
                
                // 获取选项文本(如果有)
                const options = [];
                document.querySelectorAll('.answer_list li label, .answer_list_box li label').forEach(label => {
                    options.push(label.textContent.trim());
                });
                
                // 获取当前题号
                const questionNumber = document.querySelector('.exam_pages span')?.textContent?.split('/')[0] || '';
                
                // 获取题目ID
                const questionId = document.querySelector('.answer_list ul')?.getAttribute('qid') || 
                                 document.querySelector('.answer_list_box ul')?.getAttribute('qid') ||
                                 document.querySelector('.exam_label_btn')?.getAttribute('data-val') || '';
                
                // 获取当前题目索引
                const questionIndex = document.querySelector('.answer_list ul')?.getAttribute('qindex') || 
                                     document.querySelector('.answer_list_box ul')?.getAttribute('qindex') ||
                                     document.querySelector('.exam_label_btn')?.getAttribute('data-index') || '';
                
                return {
                    title: questionTitle,
                    type: questionType,
                    options: options,
                    number: questionNumber,
                    id: questionId,
                    index: questionIndex
                };
            } catch (e) {
                console.error('获取题目信息失败:', e);
                return null;
            }
        },
        
        // 清除所有定时器
        clearAllTimers: () => {
            // 清除原页面定时器
            clearInterval(window.timer);
            window.clearInterval(window.loop_flag);
            window.clearInterval(window.flag);
    
            // 清除我们自己的定时器
            if (window.autoInterval) {
                clearInterval(window.autoInterval);
                window.autoInterval = null;
            }
            
            // 清除答题定时器
            if (window.answerInterval) {
                clearInterval(window.answerInterval);
                window.answerInterval = null;
            }
        },
        
        // 处理各种弹窗
        handleDialogs: () => {
            document.querySelectorAll(".public_close, .public_cancel, .public_submit, .public_cont1").forEach(btn => {
                if (btn) {
                    if (btn.textContent?.includes("继续观看") || btn.textContent?.includes("我知道了") || btn.textContent?.includes("继续")) {
                        btn.click();
                    }
                }
            });
        },
        
        // 用于防止页面监测
        preventDetection: () => {
            // 防止页面切换时暂停
            const originAddListener = Document.prototype.addEventListener;
            Document.prototype.addEventListener = function(type, listener, options) {
                if (type === "visibilitychange") return;
                return originAddListener.call(this, type, listener, options);
            };
            Object.defineProperty(document, 'hidden', { configurable: true, get: () => false });
            Object.defineProperty(document, 'visibilityState', { configurable: true, get: () => 'visible' });
        }
    };
    
    // AI接口
    const ai = {
        // 调用AI API
        callAI: (question, options, type) => {
            return new Promise((resolve, reject) => {
                if (!config.ai.apiKey) {
                    reject("请先设置API Key");
                    return;
                }
                
                // 构建prompt
                let prompt = `请帮我回答以下问题,直接给出答案选项编号,不要任何解释。\n问题: ${question}\n`;
                
                // 添加题型信息
                prompt += `题型: ${type}\n\n`;
                
                // 只有单选题和多选题需要拼接选项
                if ((type === '单选题' || type === '多选题') && options && options.length > 0) {
                    prompt += "选项:\n";
                    
                    // 根据题型设置选项前缀
                    options.forEach((option, index) => {
                        // 单选题用A,B,C,D标记,多选题用数字标记
                        const prefix = type === '多选题' ? (index + 1) : String.fromCharCode(65 + index);
                        prompt += `${prefix}. ${option}\n`;
                    });
                } else if (type === '判断题') {
                    // 判断题直接提示回答正确或错误
                    prompt += "这是一道判断题,请判断题目描述是否正确。\n";
                } else if (type === '填空题') {
                    prompt += "这是一道填空题,请直接给出答案。\n";
                }
                
                // 根据题型调整prompt的要求
                if (type === '单选题') {
                    prompt += "\n只需回答一个选项编号(A/B/C/D),不要任何多余文字。";
                } else if (type === '多选题') {
                    prompt += "\n回答格式: 数字序号,用逗号分隔,如'1,3,4',不要任何多余文字。";
                } else if (type === '判断题') {
                    prompt += "\n只需回答'正确'或'错误',不要任何多余文字。";
                } else {
                    prompt += "\n请直接给出答案,简明扼要。";
                }
                
                console.log("发送AI请求: ", {
                    url: config.ai.modelUrl,
                    model: config.ai.modelName,
                    prompt: prompt
                });
                
                // 调用API
                GM_xmlhttpRequest({
                    method: "POST",
                    url: config.ai.modelUrl,
                    headers: {
                        "Content-Type": "application/json",
                        "Authorization": `Bearer ${config.ai.apiKey}`
                    },
                    data: JSON.stringify({
                        model: config.ai.modelName,
                        messages: [
                            {
                                role: "system",
                                content: "你是一个擅长党建知识的考试助手,你的回答必须简洁,只提供答案,不解释原因。"
                            },
                            {
                                role: "user",
                                content: prompt
                            }
                        ],
                        temperature: config.ai.temperature,
                        max_tokens: config.ai.maxTokens
                    }),
                    timeout: config.ai.apiTimeout,
                    onload: function(response) {
                        try {
                            console.log("AI响应状态: ", response.status);
                            
                            // 处理非200响应
                            if (response.status !== 200) {
                                reject(`API请求失败,状态码: ${response.status}, 信息: ${response.statusText}`);
                                return;
                            }
                            
                            const result = JSON.parse(response.responseText);
                            if (result.choices && result.choices[0]) {
                                const answer = result.choices[0].message.content.trim();
                                
                                // 简单处理回答
                                let processedAnswer = answer;
                                
                                // 对单选题回答处理字母格式
                                if (type === '单选题') {
                                    // 提取第一个字母作为答案
                                    const letterMatch = answer.match(/[A-Da-d]/);
                                    if (letterMatch) {
                                        processedAnswer = letterMatch[0].toUpperCase();
                                    }
                                }
                                
                                // 对多选题处理,确保格式正确
                                if (type === '多选题') {
                                    // 提取所有数字
                                    const numbersMatch = answer.match(/\d+/g);
                                    if (numbersMatch) {
                                        processedAnswer = numbersMatch.join(',');
                                    }
                                }
                                
                                // 处理判断题答案
                                if (type === '判断题') {
                                    // 使用更强大的判断逻辑
                                    const lowerAnswer = answer.toLowerCase().trim();
                                    
                                    // 判断"正确"的各种表达方式
                                    if (lowerAnswer.includes('正确') || 
                                        lowerAnswer.includes('对') || 
                                        lowerAnswer.includes('√') || 
                                        lowerAnswer.includes('true') || 
                                        lowerAnswer.includes('right') || 
                                        lowerAnswer === 'a' || 
                                        lowerAnswer === 't' || 
                                        lowerAnswer === 'yes' || 
                                        lowerAnswer === 'y') {
                                        processedAnswer = '正确';
                                    }
                                    // 判断"错误"的各种表达方式
                                    else if (lowerAnswer.includes('错误') || 
                                             lowerAnswer.includes('错') || 
                                             lowerAnswer.includes('×') || 
                                             lowerAnswer.includes('false') || 
                                             lowerAnswer.includes('wrong') || 
                                             lowerAnswer === 'b' || 
                                             lowerAnswer === 'f' || 
                                             lowerAnswer === 'no' || 
                                             lowerAnswer === 'n') {
                                        processedAnswer = '错误';
                                    }
                                    // 如果无法识别,默认为"错误"
                                    else {
                                        console.warn(`无法识别的判断题答案: "${answer}",默认处理为"错误"`);
                                        processedAnswer = '错误';
                                    }
                                }
                                
                                console.log("AI原始回答: ", answer);
                                console.log("处理后回答: ", processedAnswer);
                                
                                resolve(processedAnswer);
                            } else {
                                reject("API返回格式错误");
                            }
                        } catch (e) {
                            reject("解析API响应失败: " + e.message);
                        }
                    },
                    onerror: function(error) {
                        reject("API请求失败: " + error);
                    },
                    ontimeout: function() {
                        reject("API请求超时");
                    }
                });
            });
        },
        
        // 获取答案(调用指定的AI模型)
        getAnswer: async (question) => {
            try {
                const info = utils.getQuestionInfo();
                if (!info) {
                    throw new Error("无法获取题目信息");
                }
                
                // 记录到控制台
                console.log(`正在解答题目: ${info.title}`);
                console.log(`题目类型: ${info.type}`);
                console.log(`选项: `, info.options);
                
                // 更新UI显示为等待状态
                ui.updateAIAnswerStatus('waiting');
                
                // 调用API获取答案
                const answer = await ai.callAI(info.title, info.options, info.type);
                
                // 更新UI显示为成功状态
                ui.updateAIAnswerStatus('success', answer);
                
                console.log(`AI回答: ${answer}`);
                return {
                    answer: answer,
                    info: info
                };
            } catch (error) {
                console.error("获取答案失败:", error);
                
                // 更新UI显示为错误状态
                ui.updateAIAnswerStatus('error', error.message);
                
                // 返回错误信息
                return null;
            }
        }
    };
    
    // 考试功能
    const exam = {
        // 封装不同题型的答题函数
        handlers: {
            // 处理单选题
            handleSingleChoice: (answer, options) => {
                try {
                    // 处理单选题,转换A,B,C,D为数字索引
                    let index = -1;
                    
                    // 支持多种格式的单选答案
                    if (/^[A-Da-d]$/.test(answer.trim())) {
                        // 如果是A、B、C、D格式
                        index = answer.trim().toUpperCase().charCodeAt(0) - 65; // 'A'=0, 'B'=1, ...
                    } else if (/^\d+$/.test(answer.trim())) {
                        // 如果是数字格式 (1、2、3、4)
                        index = parseInt(answer.trim()) - 1;
                    }
                    
                    const labels = document.querySelectorAll('.answer_list li label');
                    
                    if (index >= 0 && index < labels.length) {
                        // 点击对应选项
                        console.log(`选择单选选项: ${index + 1}`);
                        labels[index].click();
                        return true;
                    } else {
                        throw new Error(`无效的单选答案索引: ${answer} -> ${index}`);
                    }
                } catch (error) {
                    console.error("单选题处理失败:", error);
                    throw error;
                }
            },
            
            // 处理多选题
            handleMultipleChoice: (answer, options) => {
                return new Promise((resolve, reject) => {
                    try {
                        // 处理多选题,答案格式为: "1,2,3" 或 "1,3,4"
                        let selectedIndexes = [];
                        
                        // 支持多种格式的多选答案
                        if (answer.includes(',')) {
                            // 处理以逗号分隔的格式
                            selectedIndexes = answer.split(',').map(num => {
                                const trimmed = num.trim();
                                return /^\d+$/.test(trimmed) ? parseInt(trimmed) - 1 : -1;
                            }).filter(idx => idx >= 0);
                        } else if (/^[A-Za-z]+$/.test(answer.trim())) {
                            // 处理字母格式 (如 "ACD")
                            selectedIndexes = Array.from(answer.trim().toUpperCase()).map(char => {
                                return char.charCodeAt(0) - 65;
                            }).filter(idx => idx >= 0 && idx < 26);
                        } else {
                            // 尝试提取所有数字
                            const matches = answer.match(/\d+/g);
                            if (matches) {
                                selectedIndexes = matches.map(num => parseInt(num) - 1);
                            }
                        }
                        
                        const labels = document.querySelectorAll('.answer_list_box li label');
                        
                        if (selectedIndexes.length === 0) {
                            throw new Error(`无法从答案中提取选项: ${answer}`);
                        }
                        
                        console.log(`选择多选选项: ${selectedIndexes.map(i => i + 1).join(',')}`);
                        
                        // 使用循环队列处理多选项的点击,避免递归调用可能导致的问题
                        let currentIndex = 0;
                        
                        // 创建间隔计时器,逐一点击选项
                        const clickInterval = setInterval(() => {
                            if (currentIndex >= selectedIndexes.length) {
                                // 所有选项都已点击完毕
                                clearInterval(clickInterval);
                                console.log("多选题选项已全部选择完毕");
                                resolve(true);
                                return;
                            }
                            
                            const optionIndex = selectedIndexes[currentIndex];
                            if (optionIndex >= 0 && optionIndex < labels.length) {
                                console.log(`选择多选选项 ${currentIndex + 1}/${selectedIndexes.length}: 选项=${optionIndex + 1}`);
                                labels[optionIndex].click();
                            } else {
                                console.warn(`无效的多选选项索引: ${optionIndex}`);
                            }
                            
                            // 移至下一个选项
                            currentIndex++;
                        }, 300); // 每300毫秒点击一个选项
                    } catch (error) {
                        console.error("多选题处理失败:", error);
                        reject(error);
                    }
                });
            },
            
            // 处理判断题
            handleJudgement: (answer, options) => {
                try {
                    // 处理判断题
                    let isCorrect = false;
                    
                    // 使用更强大的判断逻辑
                    const lowerAnswer = answer.toLowerCase().trim();
                    
                    // 判断"正确"的各种表达方式
                    if (lowerAnswer.includes('正确') || 
                        lowerAnswer.includes('对') || 
                        lowerAnswer.includes('√') || 
                        lowerAnswer.includes('true') || 
                        lowerAnswer.includes('right') || 
                        lowerAnswer === 'a' || 
                        lowerAnswer === 't' || 
                        lowerAnswer === 'yes' || 
                        lowerAnswer === 'y') {
                        isCorrect = true;
                    }
                    // 其他情况视为"错误"
                    
                    // 获取所有选项
                    const labels = document.querySelectorAll('.answer_list li label');
                    
                    // 默认假设第一个是"正确",第二个是"错误"
                    let correctOptionIndex = -1;
                    let wrongOptionIndex = -1;
                    
                    // 遍历选项文本,查找正确和错误选项
                    for (let i = 0; i < labels.length; i++) {
                        const optionText = labels[i].textContent.trim().toLowerCase();
                        
                        if (optionText.includes('正确') || optionText.includes('对') || 
                            optionText.includes('√') || optionText.includes('true') || 
                            optionText.includes('right') || optionText === 'a') {
                            correctOptionIndex = i;
                        } else if (optionText.includes('错误') || optionText.includes('错') || 
                                  optionText.includes('×') || optionText.includes('false') || 
                                  optionText.includes('wrong') || optionText === 'b') {
                            wrongOptionIndex = i;
                        }
                    }
                    
                    // 如果没有找到明确的选项,使用默认方式处理
                    if (correctOptionIndex === -1) correctOptionIndex = 0;
                    if (wrongOptionIndex === -1) wrongOptionIndex = 1;
                    
                    // 根据AI回答选择选项
                    const indexToClick = isCorrect ? correctOptionIndex : wrongOptionIndex;
                    console.log(`选择判断: ${isCorrect ? '正确' : '错误'} (选项索引: ${indexToClick})`);
                    
                    // 点击对应选项
                    if (indexToClick >= 0 && indexToClick < labels.length) {
                        labels[indexToClick].click();
                        return true;
                    } else {
                        throw new Error(`判断题选项不存在: ${indexToClick}`);
                    }
                } catch (error) {
                    console.error("判断题处理失败:", error);
                    throw error;
                }
            },
            
            // 处理填空题
            handleFillBlank: (answer, options) => {
                try {
                    const inputField = document.querySelector('.summary_question');
                    if (inputField) {
                        inputField.value = answer;
                        // 触发blur事件以保存答案
                        inputField.dispatchEvent(new Event('input'));
                        inputField.dispatchEvent(new Event('change'));
                        inputField.dispatchEvent(new Event('blur'));
                        console.log(`填空: ${answer}`);
                        return true;
                    } else {
                        throw new Error("未找到填空输入框");
                    }
                } catch (error) {
                    console.error("填空题处理失败:", error);
                    throw error;
                }
            }
        },
        
        // 回答当前题目
        answerCurrentQuestion: async () => {
            try {
                // 使用更新状态函数更新UI
                ui.updateAIAnswerStatus('waiting');
                
                // 获取AI答案
                const result = await ai.getAnswer();
                if (!result) {
                    throw new Error("获取答案失败");
                }
                
                const { answer, info } = result;
                
                // 根据题型调用相应的处理函数
                let success = false;
                
                switch (info.type) {
                    case '单选题':
                        success = exam.handlers.handleSingleChoice(answer, info.options);
                        break;
                    case '多选题':
                        success = await exam.handlers.handleMultipleChoice(answer, info.options);
                        break;
                    case '判断题':
                        success = exam.handlers.handleJudgement(answer, info.options);
                        break;
                    case '填空题':
                        success = exam.handlers.handleFillBlank(answer, info.options);
                        break;
                    default:
                        throw new Error(`未知题型: ${info.type}`);
                }
                
                if (!success) {
                    throw new Error(`答题失败: ${info.type}`);
                }
                
                // 显示答题结果
                ui.showMessage(`回答成功: ${answer}`, 'success');
                
                return true;
            } catch (error) {
                // 使用更新状态函数更新错误状态
                ui.updateAIAnswerStatus('error', error.message);
                
                ui.showMessage(`回答失败: ${error.message}`, 'error');
                console.error("回答题目失败:", error);
                return false;
            }
        }
    };
    
    // 课程功能
    const course = {
        // 添加学习时长 - 参数为要添加的秒数
        addStudyTime: (seconds) => {
            const rid = utils.getRid();
            const video = utils.getVideo();
    
            if (!video || !rid || seconds <= 0) return false;
    
            // 计算目标时间
            const currentTime = video.currentTime || 0;
            const duration = video.duration || 600;
            // 减少2秒,等待网址自动上报完成事件
            const targetTime = Math.min(duration-2, currentTime + seconds);
    
            // 发送请求并设置视频时间
            let success = false;
    
            $.ajax({
                type: "POST",
                cache: false,
                dataType: "json",
                url: "/jjfz/lesson/current_time",
                data: {
                    rid: rid,
                    time: targetTime,
                    _xsrf: $(":input[name='_xsrf']").val()
                },
                async: false,
                success: function(data) {
                    if (data && data.code === 1) {
                        try {
                            video.currentTime = targetTime;
                            success = true;
                        } catch (e) {
                            success = false;
                        }
                    } else {
                        success = false;
                    }
                },
                error: function() {
                    success = false;
                }
            });
    
            return success;
        },
    
        // 自动播放下一集
        playNextVideo: () => {
            const current = document.querySelector('.video_red1')?.closest('li');
            const next = current?.nextElementSibling;
    
            if (next && next.querySelector('a')) {
                next.querySelector('a').click();
                return true;
            } else {
                GM_notification({ text: '✅ 本章播放完成,跳转课程列表页~', timeout: 4000 });
                location.href = `${location.protocol}//${location.host}/jjfz/lesson`;
                return false;
            }
        },
    
        // 处理视频结束事件
        handleVideoEnded: () => {
            utils.clearAllTimers();
            if (config.course.autoNext) {
                // 等待2秒,确保视频结束事件触发
                setTimeout(course.playNextVideo, 2000);
            }
        },
    
        // 启动自动学习
        startAutoLearning: () => {
            if (!config.course.autoPlay || window.autoInterval) return;
    
            // 处理弹窗
            utils.handleDialogs();
    
            // 监听视频结束事件
            const video = utils.getVideo();
            if (video && !video.hasEndedListener) {
                video.addEventListener('ended', function() {
                    console.log("视频播放结束");
                    course.handleVideoEnded();
                });
                video.hasEndedListener = true;
            }
    
            // 启动定时器
            window.autoInterval = setInterval(() => {
                const video = utils.getVideo();
                if (!video) return;
    
                // 尝试点击播放按钮
                if (video.paused) {
                    const playButton = document.querySelector('.plyr__controls [data-plyr="play"], .plyr__play-large, [aria-label="播放"]');
                    if (playButton) {
                        playButton.click();
                    } else {
                        // 触发点击事件
                        video.dispatchEvent(new MouseEvent('click', {
                            bubbles: true,
                            cancelable: true
                        }));
                    }
                    video.play();
                }
    
                // 自动处理弹窗
                utils.handleDialogs();
    
                // 更新界面
                ui.updateCourseStatus();
    
                // 检测视频是否接近结束但尚未触发ended事件
                if (video.currentTime > video.duration * 0.98 && !video.ended) {
                    video.currentTime = video.duration; // 强制跳到结尾触发ended事件
                }
            }, 1500);
        },
        
        // 停止自动学习
        stopAutoLearning: () => {
            utils.clearAllTimers();
            config.course.autoPlay = false;
            saveConfig();
            ui.showMessage('自动学习已停止', 'info');
        }
    };
    
    // UI界面
    const ui = {
        // 添加CSS样式
        addStyles: () => {
            GM_addStyle(`
                /* 主面板样式 */
                .helper-panel {
                    position: fixed;
                    top: 110px;
                    left: 10px;
                    background: #fff;
                    border-radius: 4px;
                    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
                    z-index: 9999;
                    padding: 12px;
                    width: 400px;
                    font-size: 14px;
                    margin-top: -1px;
                    max-height: 80vh;
                    overflow-y: auto;
                }
                
                /* 面板标题 */
                .helper-panel h3 {
                    margin: 0 0 10px 0;
                    padding-bottom: 8px;
                    border-bottom: 1px solid #eee;
                    text-align: center;
                    font-size: 16px;
                    color: #e61d1d;
                    font-weight: bold;
                }
                
                /* 标签页 */
                .helper-tabs {
                    display: flex;
                    margin-bottom: 10px;
                    border-bottom: 1px solid #eee;
                }
                
                .helper-tab {
                    flex: 1;
                    text-align: center;
                    padding: 6px 0;
                    cursor: pointer;
                    border-bottom: 2px solid transparent;
                    font-weight: 500;
                    transition: all 0.2s ease;
                }
                
                .helper-tab:hover {
                    background-color: #f5f5f5;
                }
                
                .helper-tab.active {
                    color: #2196F3;
                    border-bottom: 2px solid #2196F3;
                    font-weight: bold;
                }
                
                /* 内容区域 */
                .helper-content {
                    display: none;
                    padding: 5px 0;
                }
                
                .helper-content.active {
                    display: block;
                }
                
                /* 选项区域 */
                .helper-option {
                    margin-bottom: 12px;
                }
                
                .helper-option label {
                    display: block;
                    margin-bottom: 4px;
                    font-weight: bold;
                    font-size: 13px;
                }
                
                /* 复选框包装 */
                .checkbox-wrapper {
                    display: flex;
                    align-items: center;
                    margin: 5px 0;
                    padding: 2px 0;
                }
                
                .checkbox-wrapper input[type="checkbox"] {
                    width: auto;
                    margin: 0 6px 0 0;
                    cursor: pointer;
                }
                
                .checkbox-wrapper label {
                    margin: 0;
                    font-weight: normal;
                    cursor: pointer;
                }
                
                /* 表单元素 */
                .helper-panel select, 
                .helper-panel input, 
                .helper-panel button {
                    width: 100%;
                    padding: 6px 8px;
                    border: 1px solid #ddd;
                    border-radius: 3px;
                    margin-bottom: 6px;
                    cursor: pointer;
                    font-size: 13px;
                }
                
                .helper-panel select, 
                .helper-panel input[type="text"], 
                .helper-panel input[type="password"],
                .helper-panel input[type="number"] {
                    cursor: auto;
                    transition: border-color 0.2s ease;
                }
                
                .helper-panel select:focus, 
                .helper-panel input[type="text"]:focus, 
                .helper-panel input[type="password"]:focus,
                .helper-panel input[type="number"]:focus {
                    border-color: #2196F3;
                    outline: none;
                }
                
                /* 按钮样式 */
                .helper-panel button {
                    background: #2196F3;
                    color: white;
                    border: none;
                    font-weight: bold;
                    transition: background 0.2s ease, transform 0.1s ease;
                }
                
                .helper-panel button:hover {
                    background: #1976D2;
                }
                
                .helper-panel button:active {
                    transform: scale(0.98);
                }
                
                .helper-panel button.stop {
                    background: #F44336;
                }
                
                .helper-panel button.stop:hover {
                    background: #D32F2F;
                }
                
                /* 信息显示区域 */
                .helper-status {
                    background: #f8f8f8;
                    padding: 8px 10px;
                    border-radius: 3px;
                    border: 1px solid #eee;
                    margin-top: 5px;
                }
                
                .helper-status p {
                    margin: 4px 0;
                    font-size: 13px;
                    display: flex;
                    justify-content: space-between;
                }
                
                .helper-status p span {
                    max-width: 280px;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }
                
                /* 切换按钮 */
                .helper-toggle {
                    position: fixed;
                    top: 80px;
                    left: 10px;
                    background: #2196F3;
                    color: white;
                    border: none;
                    border-radius: 4px;
                    padding: 6px 12px;
                    cursor: pointer;
                    z-index: 10000;
                    font-weight: bold;
                    width: 80px;
                    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
                    transition: background 0.2s ease;
                }
                
                .helper-toggle:hover {
                    background: #1976D2;
                }
                
                /* 消息提示 */
                .helper-message {
                    position: fixed;
                    top: 10px;
                    right: 10px;
                    padding: 10px 15px;
                    border-radius: 4px;
                    z-index: 10001;
                    color: #fff;
                    font-weight: bold;
                    transition: all 0.3s ease;
                    opacity: 0;
                    transform: translateY(-20px);
                    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
                }
                
                .helper-message.show {
                    opacity: 1;
                    transform: translateY(0);
                }
                
                /* 不同类型的消息颜色 */
                .helper-message.success {
                    background: #4CAF50;
                }
                
                .helper-message.error {
                    background: #F44336;
                }
                
                .helper-message.info {
                    background: #2196F3;
                }
                
                .helper-message.warning {
                    background: #FFC107;
                    color: #333;
                }
                
                /* 高亮答案 */
                #helper-ai-answer {
                    font-family: monospace;
                    letter-spacing: 0.5px;
                }
                
                /* 设置模块内排列 */
                .settings-row {
                    display: flex;
                    gap: 8px;
                    margin-top: 8px;
                }
                
                .settings-col {
                    flex: 1;
                }
                
                .settings-col label {
                    font-weight: normal !important;
                    font-size: 12px !important;
                    color: #555;
                }
            `);
        },
        
        // 显示消息
        showMessage: (text, type = 'info') => {
            // 移除现有的消息
            const oldMessage = document.querySelector('.helper-message');
            if (oldMessage) {
                oldMessage.remove();
            }
            
            // 创建新消息
            const message = document.createElement('div');
            message.className = `helper-message ${type}`;
            message.textContent = text;
            document.body.appendChild(message);
            
            // 显示动画
            setTimeout(() => {
                message.classList.add('show');
            }, 10);
            
            // 自动消失
            setTimeout(() => {
                message.classList.remove('show');
                setTimeout(() => {
                    message.remove();
                }, 300);
            }, 1500);
        },
        
        // 更新课程状态
        updateCourseStatus: () => {
            if (!isPlayPage) return;
            
            const video = utils.getVideo();
            if (!video) return;
            
            // 当前视频标题
            const videoTitle = document.querySelector('.video_red1 a')?.textContent.trim() || "未知";
            
            // 计算进度 - 使用与原脚本相同的方式
            const total = document.querySelectorAll('.video_lists ul li').length;
            const current = Array.from(document.querySelectorAll('.video_lists ul li')).findIndex(li => li.classList.contains('video_red1')) + 1;
            
            // 更新到UI
            const videoTitleEl = document.querySelector('#helper-current-video');
            const progressEl = document.querySelector('#helper-video-progress');
            
            if (videoTitleEl) videoTitleEl.textContent = videoTitle;
            if (progressEl) progressEl.textContent = `${current}/${total}`;
            
            // 记录日志便于调试
            console.log(`学习进度: ${current}/${total}`);
        },
        
        // 更新问题状态(考试模式)
        updateExamStatus: () => {
            if (!isExamPage) return;
            
            const info = utils.getQuestionInfo();
            if (!info) return;
            
            // 检查题目是否变化
            const currentQuestionId = info.id;
            if (window.lastQuestionId !== currentQuestionId) {
                // 题目变化了,重置回答
                ui.updateAIAnswerStatus('reset');
                window.lastQuestionId = currentQuestionId;
            }
            
            // 更新到UI
            const currentQuestionEl = document.querySelector('#helper-current-question');
            const questionTypeEl = document.querySelector('#helper-question-type');
            
            if (currentQuestionEl) currentQuestionEl.textContent = info.title?.substring(0, 30) + '...';
            if (questionTypeEl) questionTypeEl.textContent = info.type;
        },
        
        // 创建面板
        createPanel: () => {
            // 创建切换按钮
            const toggleButton = document.createElement('button');
            toggleButton.className = 'helper-toggle';
            toggleButton.textContent = config.ui.panelExpanded ? '收起' : '展开';
            toggleButton.onclick = function() {
                const panel = document.querySelector('.helper-panel');
                config.ui.panelExpanded = !config.ui.panelExpanded;
                panel.style.display = config.ui.panelExpanded ? 'block' : 'none';
                this.textContent = config.ui.panelExpanded ? '收起' : '展开';
                saveConfig();
            };
            document.body.appendChild(toggleButton);
            
            // 创建面板容器
            const panel = document.createElement('div');
            panel.className = 'helper-panel';
            panel.style.display = config.ui.panelExpanded ? 'block' : 'none';
            document.body.appendChild(panel);
            
            // 面板标题
            const title = document.createElement('h3');
            title.textContent = '在线培训助手';
            panel.appendChild(title);
            
            // 创建标签页
            const tabs = document.createElement('div');
            tabs.className = 'helper-tabs';
            panel.appendChild(tabs);
            
            // 根据页面类型添加对应标签
            // 课程标签 - 仅在课程页面显示
            if (isPlayPage) {
                const courseTab = document.createElement('div');
                courseTab.className = `helper-tab ${config.ui.activeTab === 'course' ? 'active' : ''}`;
                courseTab.textContent = '课程';
                courseTab.onclick = function() {
                    if (config.ui.activeTab !== 'course') {
                        document.querySelectorAll('.helper-tab').forEach(tab => tab.classList.remove('active'));
                        document.querySelectorAll('.helper-content').forEach(content => content.classList.remove('active'));
                        this.classList.add('active');
                        document.querySelector('#helper-course-content').classList.add('active');
                        config.ui.activeTab = 'course';
                        saveConfig();
                    }
                };
                tabs.appendChild(courseTab);
                
                // 如果在课程页面,但活动标签不是课程,则自动设置为课程
                if (config.ui.activeTab !== 'course' && config.ui.activeTab !== 'settings') {
                    config.ui.activeTab = 'course';
                    saveConfig();
                }
            }
            
            // 考试标签 - 仅在考试页面显示
            if (isExamPage) {
                const examTab = document.createElement('div');
                examTab.className = `helper-tab ${config.ui.activeTab === 'exam' ? 'active' : ''}`;
                examTab.textContent = '考试';
                examTab.onclick = function() {
                    if (config.ui.activeTab !== 'exam') {
                        document.querySelectorAll('.helper-tab').forEach(tab => tab.classList.remove('active'));
                        document.querySelectorAll('.helper-content').forEach(content => content.classList.remove('active'));
                        this.classList.add('active');
                        document.querySelector('#helper-exam-content').classList.add('active');
                        config.ui.activeTab = 'exam';
                        saveConfig();
                    }
                };
                tabs.appendChild(examTab);
                
                // 如果在考试页面,但活动标签不是考试,则自动设置为考试
                if (config.ui.activeTab !== 'exam' && config.ui.activeTab !== 'settings') {
                    config.ui.activeTab = 'exam';
                    saveConfig();
                }
            }
            
            // 设置标签 - 始终显示
            const settingsTab = document.createElement('div');
            settingsTab.className = `helper-tab ${config.ui.activeTab === 'settings' ? 'active' : ''}`;
            settingsTab.textContent = '设置';
            settingsTab.onclick = function() {
                if (config.ui.activeTab !== 'settings') {
                    document.querySelectorAll('.helper-tab').forEach(tab => tab.classList.remove('active'));
                    document.querySelectorAll('.helper-content').forEach(content => content.classList.remove('active'));
                    this.classList.add('active');
                    document.querySelector('#helper-settings-content').classList.add('active');
                    config.ui.activeTab = 'settings';
                    saveConfig();
                }
            };
            tabs.appendChild(settingsTab);
            
            // 创建内容区域
            
            // 1. 课程内容 - 仅在课程页面创建
            if (isPlayPage) {
                const courseContent = document.createElement('div');
                courseContent.id = 'helper-course-content';
                courseContent.className = `helper-content ${config.ui.activeTab === 'course' ? 'active' : ''}`;
                panel.appendChild(courseContent);
                
                // 自动学习开关
                const autoLearningOption = document.createElement('div');
                autoLearningOption.className = 'helper-option';
                autoLearningOption.innerHTML = `
                    <button id="helper-toggle-auto" class="${config.course.autoPlay ? 'stop' : ''}">${config.course.autoPlay ? '⏸️ 暂停刷课' : '▶️ 开始刷课'}</button>
                `;
                courseContent.appendChild(autoLearningOption);
                
                // 快进控制
                const jumpOption = document.createElement('div');
                jumpOption.className = 'helper-option';
                jumpOption.innerHTML = `
                    <label>跳转控制</label>
                    <div style="display:flex;gap:5px;">
                        <input type="number" id="helper-jump-time" value="30" min="1" max="3600" style="flex:2;">
                        <button id="helper-jump-btn" style="flex:1;">快进(秒)⏩</button>
                    </div>
                `;
                courseContent.appendChild(jumpOption);
                
                // 课程状态
                const courseStatus = document.createElement('div');
                courseStatus.className = 'helper-status';
                courseStatus.innerHTML = `
                    <p>当前视频: <span id="helper-current-video">获取中...</span></p>
                    <p>学习进度: <span id="helper-video-progress">0/0</span></p>
                `;
                courseContent.appendChild(courseStatus);
            }
            
            // 2. 考试内容 - 仅在考试页面创建
            if (isExamPage) {
                const examContent = document.createElement('div');
                examContent.id = 'helper-exam-content';
                examContent.className = `helper-content ${config.ui.activeTab === 'exam' ? 'active' : ''}`;
                panel.appendChild(examContent);
                
                // 搜题和选择答案按钮
                const examButtonsOption = document.createElement('div');
                examButtonsOption.className = 'helper-option';
                examButtonsOption.innerHTML = `
                    <button id="helper-manual-answer">🤖 搜索并选择答案</button>
                `;
                examContent.appendChild(examButtonsOption);
                
                // 考试状态
                const examStatus = document.createElement('div');
                examStatus.className = 'helper-status';
                examStatus.innerHTML = `
                    <p>当前题目: <span id="helper-current-question">等待...</span></p>
                    <p>题目类型: <span id="helper-question-type">-</span></p>
                    <p>模型回答: <span id="helper-ai-answer">-</span></p>
                `;
                examContent.appendChild(examStatus);
            }
            
            // 3. 设置内容 - 总是创建
            const settingsContent = document.createElement('div');
            settingsContent.id = 'helper-settings-content';
            settingsContent.className = `helper-content ${config.ui.activeTab === 'settings' ? 'active' : ''}`;
            panel.appendChild(settingsContent);
            
            // AI设置
            const aiSettingsOption = document.createElement('div');
            aiSettingsOption.className = 'helper-option';
            aiSettingsOption.innerHTML = `
                <label>AI接口设置</label>
                <label style="font-weight:normal;margin-top:5px;font-size:12px;">接口URL:</label>
                <input type="text" id="helper-base-url" placeholder="完整API地址" value="${config.ai.modelUrl || ''}">
                
                <label style="font-weight:normal;margin-top:5px;font-size:12px;">模型名称:</label>
                <input type="text" id="helper-model-name" placeholder="如: gpt-4" value="${config.ai.modelName || ''}">
                
                <label style="font-weight:normal;margin-top:5px;font-size:12px;">API密钥:</label>
                <input type="password" id="helper-api-key" placeholder="API Key" value="${config.ai.apiKey || ''}">
                
                <div class="settings-row">
                    <div class="settings-col">
                        <label>温度:</label>
                        <input type="number" id="helper-temperature" value="${config.ai.temperature}" min="0" max="1" step="0.1">
                    </div>
                    <div class="settings-col">
                        <label>Token:</label>
                        <input type="number" id="helper-max-tokens" value="${config.ai.maxTokens}" min="100" max="8000" step="100">
                    </div>
                    <div class="settings-col">
                        <label>超时(ms):</label>
                        <input type="number" id="helper-api-timeout" value="${config.ai.apiTimeout}" min="5000" max="120000" step="1000">
                    </div>
                </div>
            `;
            settingsContent.appendChild(aiSettingsOption);
            
            // 保存设置按钮
            const saveSettingsOption = document.createElement('div');
            saveSettingsOption.className = 'helper-option';
            saveSettingsOption.innerHTML = `
                <button id="helper-save-settings">💾 保存设置</button>
            `;
            settingsContent.appendChild(saveSettingsOption);
        },
        
        // 初始化事件监听 - 根据页面类型添加对应事件
        setupEventListeners: () => {
            // 课程页面事件 - 仅在课程页面添加
            if (isPlayPage) {
                // 切换自动学习按钮
                document.getElementById('helper-toggle-auto')?.addEventListener('click', function() {
                    if (config.course.autoPlay) {
                        course.stopAutoLearning();
                        this.textContent = '▶️ 开始刷课';
                        this.classList.remove('stop');
                    } else {
                        config.course.autoPlay = true;
                        saveConfig();
                        course.startAutoLearning();
                        this.textContent = '⏸️ 暂停刷课';
                        this.classList.add('stop');
                    }
                });
                
                // 快进按钮
                document.getElementById('helper-jump-btn')?.addEventListener('click', function() {
                    const seconds = parseInt(document.getElementById('helper-jump-time')?.value) || 30;
                    if (course.addStudyTime(seconds)) {
                        ui.showMessage(`快进${seconds}秒成功`, 'success');
                    } else {
                        ui.showMessage('快进失败,请检查视频状态', 'error');
                    }
                });
            }
            
            // 考试页面事件 - 仅在考试页面添加
            if (isExamPage) {
                // 搜题并选择答案按钮
                document.getElementById('helper-manual-answer')?.addEventListener('click', function() {
                    exam.answerCurrentQuestion();
                });
            }
            
            // 设置页面事件 - 总是添加
            // 保存设置按钮
            document.getElementById('helper-save-settings')?.addEventListener('click', function() {
                try {
                    // 获取设置值
                    const baseUrl = document.getElementById('helper-base-url')?.value || '';
                    const modelName = document.getElementById('helper-model-name')?.value || '';
                    const apiKey = document.getElementById('helper-api-key')?.value || '';
                    const temperature = parseFloat(document.getElementById('helper-temperature')?.value) || 0.7;
                    const maxTokens = parseInt(document.getElementById('helper-max-tokens')?.value) || 500;
                    const apiTimeout = parseInt(document.getElementById('helper-api-timeout')?.value) || 30000;
                    
                    // 更新配置
                    config.ai.modelUrl = baseUrl;
                    config.ai.modelName = modelName;
                    config.ai.apiKey = apiKey;
                    config.ai.temperature = temperature;
                    config.ai.maxTokens = maxTokens;
                    config.ai.apiTimeout = apiTimeout;
                    
                    // 保存设置
                    if (saveConfig()) {
                        ui.showMessage('设置已保存', 'success');
                    } else {
                        ui.showMessage('设置保存失败', 'error');
                    }
                } catch (error) {
                    ui.showMessage(`设置保存出错: ${error.message}`, 'error');
                    console.error('保存设置错误:', error);
                }
            });
        },
        
        // 更新AI回答状态
        updateAIAnswerStatus: (status, answer = '', isError = false) => {
            const aiAnswerEl = document.querySelector('#helper-ai-answer');
            if (!aiAnswerEl) return;
            
            // 清除之前的样式
            aiAnswerEl.style.color = '';
            aiAnswerEl.style.fontWeight = 'normal';
            
            switch (status) {
                case 'waiting':
                    aiAnswerEl.textContent = "获取中...";
                    aiAnswerEl.style.color = "#2196F3";
                    break;
                    
                case 'success':
                    aiAnswerEl.textContent = answer || "获取成功";
                    aiAnswerEl.style.color = "#e61d1d";
                    aiAnswerEl.style.fontWeight = "bold";
                    break;
                    
                case 'error':
                    aiAnswerEl.textContent = answer ? `错误: ${answer}` : "获取失败";
                    aiAnswerEl.style.color = "#F44336";
                    break;
                    
                case 'reset':
                    aiAnswerEl.textContent = "-";
                    break;
                    
                default:
                    aiAnswerEl.textContent = answer || "-";
                    if (isError) {
                        aiAnswerEl.style.color = "#F44336";
                    }
            }
        }
    };
    
    // 初始化脚本
    function init() {
        // 添加样式
        ui.addStyles();
        
        // 防止页面监测
        utils.preventDetection();
        
        // 创建UI界面
        ui.createPanel();
        
        // 设置事件监听
        ui.setupEventListeners();
        
        // 根据页面类型初始化不同功能
        if (isPlayPage) {
            // 课程页面,检查是否要自动开始学习
            if (config.course.autoPlay) {
                setTimeout(() => {
                    course.startAutoLearning();
                }, 1000);
            }
            
            // 定期更新课程状态
            setInterval(() => {
                ui.updateCourseStatus();
            }, 1000);
        } else if (isExamPage) {
            // 考试页面
            
            // 定期更新考试状态
            setInterval(() => {
                ui.updateExamStatus();
            }, 1000);
            
            // 绑定答题卡点击事件
            setTimeout(() => {
                // 为答题卡中的题目添加点击事件
                document.querySelectorAll('.exam_ul li').forEach(li => {
                    li.addEventListener('click', () => {
                        // 题目切换时重置答案显示
                        setTimeout(() => {
                            ui.updateAIAnswerStatus('reset');
                        }, 200);
                    });
                });
                
                // 监听下一题和上一题按钮
                const nextBtn = document.querySelector('#next_question');
                const prevBtn = document.querySelector('#prev_question');
                
                if (nextBtn) {
                    nextBtn.addEventListener('click', () => {
                        ui.updateAIAnswerStatus('reset');
                    });
                }
                
                if (prevBtn) {
                    prevBtn.addEventListener('click', () => {
                        ui.updateAIAnswerStatus('reset');
                    });
                }
            }, 2000); // 等待页面元素完全加载
        }
    }
    
    init();
})();