Greasy Fork

来自缓存

Greasy Fork is available in English.

大模型中文翻译助手

选中文本后调用 OpenAI Compatible API 将其翻译为中文,支持历史记录、收藏夹及整页翻译

当前为 2025-03-18 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         大模型中文翻译助手
// @name:en      LLM powered WebPage Translator to Chinese
// @namespace    http://tampermonkey.net/
// @version      1.3.13
// @description  选中文本后调用 OpenAI Compatible API 将其翻译为中文,支持历史记录、收藏夹及整页翻译
// @description:en Select text and call OpenAI Compatible API to translate it to Chinese, supports history, favorites and full page translation
// @author       tzh
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // 可配置的设置
    const defaultSettings = {
        apiEndpoint: 'https://api.deepseek.com/v1/chat/completions', // 默认 OpenAI API 端点
        apiKey: '', // 设置您的 API 密钥
        model: 'deepseek-chat', // 可以根据需要更改为其他模型
        systemPrompt: '你是一个翻译助手。我会为你提供待翻译的文本,以及之前已经翻译过的上下文(如果有)。请参考这些上下文,将文本准确地翻译成中文,保持原文的意思、风格和格式。在充分保留原文意思的情况下使用符合中文习惯的表达。只返回翻译结果,不需要解释。',
        useStreaming: false, // 默认启用流式响应
        temperature: 0.3, // 控制翻译结果的随机性,值越低越准确,值越高越有创意
        maxHistoryItems: 50, // 最大历史记录数
        maxFavoritesItems: 100, // 最大收藏数
        showSourceLanguage: false, // 是否显示源语言
        autoDetectLanguage: true, // 是否自动检测语言
        detectArticleContent: true, // 是否自动识别文章主体内容
        contextSize: 3, // 翻译时使用的上下文数量
        useTranslationContext: true, // 是否启用翻译上下文
        fullPageTranslationSelector: 'body', // 整页翻译时的选择器
        fullPageMaxSegmentLength: 2000, // 整页翻译时的最大分段长度
        excludeSelectors: 'script, style, noscript, iframe, img, svg, canvas', // 翻译时排除的元素
        apiConfigs: [ // 多API配置
            {
                name: 'DeepSeek',
                apiEndpoint: 'https://api.deepseek.com/v1/chat/completions',
                apiKey: '',
                model: 'deepseek-chat',
            }
        ],
        currentApiIndex: 0, // 当前使用的API索引
        currentTab: 'general', // 默认显示普通设置标签
    };

    // 初始化设置
    let settings = GM_getValue('translatorSettings', defaultSettings);

    // 全文翻译相关状态
    let isTranslatingFullPage = false; // 是否正在进行全文翻译
    let isTranslationPaused = false; // 是否已暂停翻译
    let translationSegments = []; // 存储页面分段内容
    let lastTranslatedIndex = -1; // 最后翻译的段落索引
    let originalTexts = []; // 存储原始文本

    // 确保设置中包含apiConfigs字段
    if (!settings.apiConfigs) {
        settings.apiConfigs = [
            {
                name: '默认API',
                apiEndpoint: settings.apiEndpoint,
                apiKey: settings.apiKey,
                model: settings.model,
            }
        ];
        settings.currentApiIndex = 0;
        GM_setValue('translatorSettings', settings);
    }

    // 从当前选择的API配置中同步主要设置
    function syncApiSettings() {
        if (settings.apiConfigs && settings.apiConfigs.length > 0 && settings.currentApiIndex >= 0 && settings.currentApiIndex < settings.apiConfigs.length) {
            const currentApi = settings.apiConfigs[settings.currentApiIndex];
            settings.apiEndpoint = currentApi.apiEndpoint;
            settings.apiKey = currentApi.apiKey;
            settings.model = currentApi.model;
            GM_setValue('translatorSettings', settings);
        }
    }

    // 初始同步
    syncApiSettings();

    let translationHistory = GM_getValue('translationHistory', []);
    let translationFavorites = GM_getValue('translationFavorites', []);

    // 跟踪当前活跃的翻译按钮
    let activeTranslateButton = null;
    let lastSelectedText = '';
    let lastSelectionRect = null;

    // 监听整个文档的mousedown事件,防止点击翻译按钮时丢失选择
    document.addEventListener('mousedown', function (e) {
        // 检查点击是否发生在翻译按钮上
        if (e.target.classList.contains('translate-button') || e.target.closest('.translate-button')) {
            e.stopPropagation();
            e.preventDefault();
        }
    }, true);  // 使用捕获阶段,确保在其他处理程序之前执行

    // 语言检测函数
    function detectLanguage(text) {
        return new Promise((resolve) => {
        // 简单的语言检测逻辑
        const chineseRegex = /[\u4e00-\u9fa5]/;
        const englishRegex = /[a-zA-Z]/;
        const japaneseRegex = /[\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FAF]/;
        const koreanRegex = /[\uAC00-\uD7AF\u1100-\u11FF]/;

            if (chineseRegex.test(text)) resolve('中文');
            else if (englishRegex.test(text)) resolve('英语');
            else if (japaneseRegex.test(text)) resolve('日语');
            else if (koreanRegex.test(text)) resolve('韩语');
            else resolve('未知');
        });
    }

    // 创建设置面板
    function createSettingsPanel() {
        const settingsPanel = document.createElement('div');
        settingsPanel.id = 'translator-settings-panel';
        settingsPanel.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 500px;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
            z-index: 10000;
            height: 90vh;
            display: none;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            font-size: 14px;
            line-height: 1.5;
            color: #333;
        `;

        // 创建Tab栏
        const tabsHtml = `
            <div class="settings-header" style="padding: 0; flex: 0 0 auto;">
                <div class="settings-tabs" style="border-bottom: 1px solid #eee;">
                    <div class="tab-buttons" style="display: flex;">
                        <button id="general-tab-btn" class="tab-btn ${settings.currentTab === 'general' ? 'active' : ''}" 
                            style="flex: 1; padding: 12px 15px; background: none; border: none; border-bottom: 2px solid ${settings.currentTab === 'general' ? '#4285f4' : 'transparent'}; 
                            cursor: pointer; color: ${settings.currentTab === 'general' ? '#4285f4' : '#666'}; font-size: 14px; font-weight: 500; outline: none;">
                            翻译设置
                        </button>
                        <button id="api-tab-btn" class="tab-btn ${settings.currentTab === 'api' ? 'active' : ''}" 
                            style="flex: 1; padding: 12px 15px; background: none; border: none; border-bottom: 2px solid ${settings.currentTab === 'api' ? '#4285f4' : 'transparent'}; 
                            cursor: pointer; color: ${settings.currentTab === 'api' ? '#4285f4' : '#666'}; font-size: 14px; font-weight: 500; outline: none;">
                            API 管理
                        </button>
                    </div>
                </div>
            </div>
        `;

        // 创建内容区域的容器
        const contentContainerHtml = `
            <div class="settings-content" style="flex: 1 1 auto; overflow-y: auto; padding: 20px;">
                <div id="general-tab" class="tab-content" style="display: ${settings.currentTab === 'general' ? 'block' : 'none'};">
                    <h2 style="margin: 0 0 20px 0; font-size: 18px; font-weight: 500; color: #333;">翻译设置</h2>
                    <div style="margin-bottom: 20px;">
                        <label for="systemPrompt" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">系统提示词:</label>
                        <textarea id="systemPrompt" style="width: 100%; height: 100px; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; line-height: 1.5; resize: vertical; font-family: inherit;">${settings.systemPrompt}</textarea>
                    </div>
                    <div style="margin-bottom: 20px;">
                        <label for="temperature" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">随机性(Temperature)</label>
                        <div style="display: flex; align-items: center;">
                            <input type="range" id="temperature" min="0" max="1" step="0.1" value="${settings.temperature}" 
                                style="flex-grow: 1; height: 4px; background: #ddd; border-radius: 2px; outline: none; -webkit-appearance: none;">
                            <span id="temperature-value" style="margin-left: 15px; min-width: 30px; color: #666;">${settings.temperature}</span>
                        </div>
                        <div style="font-size: 12px; color: #666; margin-top: 8px;">
                            值越低翻译越准确,值越高结果越具有创意性。翻译任务建议使用较低的值。
                        </div>
                    </div>
                    <div style="margin-bottom: 15px;">
                        <label style="display: flex; align-items: center; color: #333;">
                            <input type="checkbox" id="showSourceLanguage" ${settings.showSourceLanguage ? 'checked' : ''} 
                                style="margin: 0 8px 0 0; width: 16px; height: 16px;">
                            <span style="font-weight: 500;">显示原文</span>
                        </label>
                        <div style="font-size: 12px; color: #666; margin-top: 8px; margin-left: 24px;">
                            启用后将在翻译结果上方显示原文
                        </div>
                    </div>
                    <div style="margin-bottom: 15px;">
                        <label style="display: flex; align-items: center; color: #333;">
                            <input type="checkbox" id="useStreaming" ${settings.useStreaming ? 'checked' : ''} 
                                style="margin: 0 8px 0 0; width: 16px; height: 16px;">
                            <span style="font-weight: 500;">启用流式响应(实时显示翻译结果)</span>
                        </label>
                        <div style="font-size: 12px; color: #666; margin-top: 8px; margin-left: 24px;">
                            如果遇到翻译失败问题,可以尝试关闭此选项
                        </div>
                    </div>
                    <div style="margin-bottom: 15px;">
                        <label style="display: flex; align-items: center; color: #333;">
                            <input type="checkbox" id="useTranslationContext" ${settings.useTranslationContext ? 'checked' : ''} 
                                style="margin: 0 8px 0 0; width: 16px; height: 16px;">
                            <span style="font-weight: 500;">启用翻译上下文</span>
                        </label>
                        <div style="font-size: 12px; color: #666; margin-top: 8px; margin-left: 24px;">
                            启用后将使用之前翻译过的内容作为上下文,提高翻译连贯性
                        </div>
                    </div>
                    <div style="margin-bottom: 20px;">
                        <label for="contextSize" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">上下文数量:</label>
                        <div style="display: flex; align-items: center;">
                            <input type="number" id="contextSize" min="1" max="10" value="${settings.contextSize}" 
                                style="width: 60px; padding: 6px 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
                            <span style="margin-left: 10px; color: #666;">段落</span>
                        </div>
                        <div style="font-size: 12px; color: #666; margin-top: 8px;">
                            使用前面已翻译段落作为上下文提升翻译连贯性,建议设置1-5之间,设置较大值会降低翻译速度,消耗更多API配额
                        </div>
                    </div>
                    <div style="margin-bottom: 15px;">
                        <label style="display: flex; align-items: center; color: #333;">
                            <input type="checkbox" id="detectArticleContent" ${settings.detectArticleContent ? 'checked' : ''} 
                                style="margin: 0 8px 0 0; width: 16px; height: 16px;">
                            <span style="font-weight: 500;">智能识别文章主体内容</span>
                        </label>
                        <div style="font-size: 12px; color: #666; margin-top: 8px; margin-left: 24px;">
                            启用后将自动识别文章主要内容区域,避免翻译无关内容
                        </div>
                    </div>
                    <div style="margin-bottom: 20px;">
                        <label for="fullPageTranslationSelector" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">整页翻译选择器:</label>
                        <input type="text" id="fullPageTranslationSelector" value="${settings.fullPageTranslationSelector}" 
                            style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
                        <div style="font-size: 12px; color: #666; margin-top: 8px;">
                            CSS选择器,用于指定翻译哪些区域的内容
                        </div>
                    </div>
                    <div style="margin-bottom: 20px;">
                        <label for="excludeSelectors" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">排除翻译的元素:</label>
                        <input type="text" id="excludeSelectors" value="${settings.excludeSelectors}" 
                            style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
                        <div style="font-size: 12px; color: #666; margin-top: 8px;">
                            CSS选择器,指定要排除翻译的元素
                        </div>
                    </div>
                </div>
                <div id="api-tab" class="tab-content" style="display: ${settings.currentTab === 'api' ? 'block' : 'none'};">
                    <h2 style="margin: 0 0 20px 0; font-size: 18px; font-weight: 500; color: #333;">API 管理</h2>
                    <button id="add-api-btn" style="width: 100%; padding: 12px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; font-size: 14px; font-weight: 500; cursor: pointer; margin-bottom: 20px;">
                        + 添加新 API
                    </button>
                    <div id="api-list">
                        ${settings.apiConfigs.map((api, index) => `
                            <div class="api-item" style="margin-bottom: 15px; padding: 15px; border: 1px solid #ddd; border-radius: 4px; position: relative; ${index === settings.currentApiIndex ? 'background-color: #f0f8ff; border-color: #4285f4;' : ''}">
                                <div style="position: absolute; top: 15px; right: 15px;">
                                    ${index === settings.currentApiIndex ?
                                        '<span style="color: #4CAF50; font-weight: 500;">✓ 当前使用</span>' :
                                        `<button class="use-api-btn" data-index="${index}" style="padding: 4px 12px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 8px; font-size: 12px;">使用</button>`
                                    }
                                    <button class="edit-api-btn" data-index="${index}" style="padding: 4px 12px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 8px; font-size: 12px;">编辑</button>
                                    ${settings.apiConfigs.length > 1 ?
                                        `<button class="delete-api-btn" data-index="${index}" style="padding: 4px 12px; background-color: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;">删除</button>` : ''
                                    }
                                </div>
                                <div style="margin-bottom: 8px;"><strong style="color: #333;">名称:</strong> <span style="color: #666;">${api.name}</span></div>
                                <div style="margin-bottom: 8px;"><strong style="color: #333;">端点:</strong> <span style="color: #666;">${api.apiEndpoint}</span></div>
                                <div style="margin-bottom: 8px;"><strong style="color: #333;">密钥:</strong> <span style="color: #666;">${api.apiKey ? '******' + api.apiKey.substring(api.apiKey.length - 4) : '未设置'}</span></div>
                                <div><strong style="color: #333;">模型:</strong> <span style="color: #666;">${api.model}</span></div>
                            </div>
                        `).join('')}
                    </div>
                </div>
            </div>
        `;

        // 创建API编辑表单
        const apiFormHtml = `
            <div id="api-form" style="display: none; padding: 20px; overflow-y: auto; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: white;">
                <h2 id="api-form-title" style="margin: 0 0 20px 0; font-size: 18px; font-weight: 500; color: #333;">添加 API</h2>
                <input type="hidden" id="api-form-index" value="-1">
                <div style="margin-bottom: 20px;">
                    <label for="api-name" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">API 名称:</label>
                    <input type="text" id="api-name" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;" placeholder="例如:OpenAI、Azure、DeepSeek">
                </div>
                <div style="margin-bottom: 20px;">
                    <label for="api-endpoint" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">API 端点:</label>
                    <input type="text" id="api-endpoint" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;" placeholder="例如:https://api.openai.com/v1/chat/completions">
                </div>
                <div style="margin-bottom: 20px;">
                    <label for="api-key" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">API 密钥:</label>
                    <input type="password" id="api-key" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;" placeholder="输入您的API密钥">
                    <div style="font-size: 12px; color: #666; margin-top: 8px;">
                        编辑现有API时,如不需要修改密钥请留空
                    </div>
                </div>
                <div style="margin-bottom: 20px;">
                    <label for="api-model" style="display: block; margin-bottom: 8px; color: #333; font-weight: 500;">模型名称:</label>
                    <input type="text" id="api-model" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;" placeholder="例如:gpt-3.5-turbo">
                </div>
                <div style="text-align: right;">
                    <button id="cancel-api-form" style="padding: 8px 20px; background: #f5f5f5; color: #333; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-right: 10px; cursor: pointer;">取消</button>
                    <button id="save-api-form" style="padding: 8px 20px; background-color: #4285f4; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">保存</button>
                </div>
            </div>
        `;

        // 创建底部按钮区域
        const footerHtml = `
            <div class="settings-footer" style="padding: 15px 20px; border-top: 1px solid #eee; text-align: right; background: white; border-radius: 0 0 8px 8px; flex: 0 0 auto;">
                <button id="cancel-settings" style="padding: 8px 20px; background: #f5f5f5; color: #333; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-right: 10px; cursor: pointer;">取消</button>
                <button id="save-settings" style="padding: 8px 20px; background-color: #4285f4; color: white; border: none; border-radius: 4px; font-size: 14px; cursor: pointer;">保存</button>
            </div>
        `;

        settingsPanel.innerHTML = tabsHtml + contentContainerHtml + apiFormHtml + footerHtml;
        document.body.appendChild(settingsPanel);

        // 工具函数:更新设置面板视图
        function updateSettingsPanelView() {
            // 更新标签页状态
            document.getElementById('general-tab').style.display = settings.currentTab === 'general' ? 'block' : 'none';
            document.getElementById('api-tab').style.display = settings.currentTab === 'api' ? 'block' : 'none';
            document.getElementById('api-form').style.display = 'none';
            
            // 更新标签按钮样式
            const generalTabBtn = document.getElementById('general-tab-btn');
            const apiTabBtn = document.getElementById('api-tab-btn');
            
            if (settings.currentTab === 'general') {
                generalTabBtn.style.borderBottom = '2px solid #4285f4';
                generalTabBtn.style.color = '#4285f4';
                apiTabBtn.style.borderBottom = '2px solid transparent';
                apiTabBtn.style.color = '#666';
            } else {
                apiTabBtn.style.borderBottom = '2px solid #4285f4';
                apiTabBtn.style.color = '#4285f4';
                generalTabBtn.style.borderBottom = '2px solid transparent';
                generalTabBtn.style.color = '#666';
            }
            
            // 更新表单值
            document.getElementById('systemPrompt').value = settings.systemPrompt;
            document.getElementById('temperature').value = settings.temperature;
            document.getElementById('temperature-value').textContent = settings.temperature;
            document.getElementById('showSourceLanguage').checked = settings.showSourceLanguage;
            document.getElementById('useStreaming').checked = settings.useStreaming;
            document.getElementById('useTranslationContext').checked = settings.useTranslationContext;
            document.getElementById('contextSize').value = settings.contextSize;
            document.getElementById('detectArticleContent').checked = settings.detectArticleContent;
            document.getElementById('fullPageTranslationSelector').value = settings.fullPageTranslationSelector;
            document.getElementById('excludeSelectors').value = settings.excludeSelectors;
            
            // 更新API列表
            updateApiList();
        }

        // 事件处理程序
        document.getElementById('general-tab-btn').addEventListener('click', function() {
            settings.currentTab = 'general';
            updateSettingsPanelView();
        });

        document.getElementById('api-tab-btn').addEventListener('click', function() {
            settings.currentTab = 'api';
            updateSettingsPanelView();
        });

        // 添加API按钮事件
        document.getElementById('add-api-btn').addEventListener('click', function() {
            document.getElementById('api-tab').style.display = 'none';
            document.getElementById('api-form').style.display = 'block';
            document.getElementById('api-form-title').textContent = '添加 API';
            document.getElementById('api-form-index').value = '-1';
            document.getElementById('api-name').value = '';
            document.getElementById('api-endpoint').value = '';
            document.getElementById('api-key').value = '';
            document.getElementById('api-model').value = '';
        });

        // API表单取消按钮事件
        document.getElementById('cancel-api-form').addEventListener('click', function() {
            document.getElementById('api-form').style.display = 'none';
            document.getElementById('api-tab').style.display = 'block';
        });

        // API表单保存按钮事件
        document.getElementById('save-api-form').addEventListener('click', function() {
            const index = parseInt(document.getElementById('api-form-index').value);
            const apiConfig = {
                name: document.getElementById('api-name').value,
                apiEndpoint: document.getElementById('api-endpoint').value,
                model: document.getElementById('api-model').value
            };

            const apiKey = document.getElementById('api-key').value;
            if (apiKey) {
                apiConfig.apiKey = apiKey;
            } else if (index !== -1) {
                apiConfig.apiKey = settings.apiConfigs[index].apiKey;
            }

            if (index === -1) {
                settings.apiConfigs.push(apiConfig);
            } else {
                settings.apiConfigs[index] = apiConfig;
            }

            document.getElementById('api-form').style.display = 'none';
            document.getElementById('api-tab').style.display = 'block';
            updateApiList();
        });

        // 设置面板的取消和保存按钮事件
        document.getElementById('cancel-settings').addEventListener('click', function() {
            settingsPanel.style.display = 'none';
        });

        document.getElementById('save-settings').addEventListener('click', function() {
            settings = {
                ...settings,
                systemPrompt: document.getElementById('systemPrompt').value,
                useStreaming: document.getElementById('useStreaming').checked,
                showSourceLanguage: document.getElementById('showSourceLanguage').checked,
                detectArticleContent: document.getElementById('detectArticleContent').checked,
                temperature: parseFloat(document.getElementById('temperature').value),
                fullPageTranslationSelector: document.getElementById('fullPageTranslationSelector').value,
                excludeSelectors: document.getElementById('excludeSelectors').value,
                useTranslationContext: document.getElementById('useTranslationContext').checked,
                contextSize: parseInt(document.getElementById('contextSize').value) || 3,
                currentTab: settings.currentTab
            };

            GM_setValue('translatorSettings', settings);
            settingsPanel.style.display = 'none';
        });

        // 绑定API列表项的事件处理程序
        function bindApiListEvents() {
            document.querySelectorAll('.use-api-btn').forEach(button => {
                button.addEventListener('click', function() {
                    const index = parseInt(this.dataset.index);
                    settings.currentApiIndex = index;
                    updateApiList();
                });
            });

            document.querySelectorAll('.edit-api-btn').forEach(button => {
                button.addEventListener('click', function() {
                    const index = parseInt(this.dataset.index);
                    const api = settings.apiConfigs[index];
                    document.getElementById('api-form-title').textContent = '编辑 API';
                    document.getElementById('api-form-index').value = index;
                    document.getElementById('api-name').value = api.name;
                    document.getElementById('api-endpoint').value = api.apiEndpoint;
                    document.getElementById('api-key').value = '';
                    document.getElementById('api-model').value = api.model;
                    
                    // 在内容区域显示API表单,而不是隐藏内容区域
                    document.getElementById('api-form').style.display = 'block';
                    document.getElementById('api-tab').style.display = 'none';
                });
            });

            document.querySelectorAll('.delete-api-btn').forEach(button => {
                button.addEventListener('click', function() {
                    const index = parseInt(this.dataset.index);
                    if (confirm('确定要删除这个API配置吗?')) {
                        settings.apiConfigs.splice(index, 1);
                        if (settings.currentApiIndex === index) {
                            settings.currentApiIndex = 0;
                        } else if (settings.currentApiIndex > index) {
                            settings.currentApiIndex--;
                        }
                        updateApiList();
                    }
                });
            });
        }

        // 更新API列表的函数
        function updateApiList() {
            const apiListHtml = settings.apiConfigs.map((api, index) => `
                <div class="api-item" style="margin-bottom: 15px; padding: 15px; border: 1px solid #ddd; border-radius: 4px; position: relative; ${index === settings.currentApiIndex ? 'background-color: #f0f8ff; border-color: #4285f4;' : ''}">
                    <div style="position: absolute; top: 15px; right: 15px;">
                        ${index === settings.currentApiIndex ?
                            '<span style="color: #4CAF50; font-weight: 500;">✓ 当前使用</span>' :
                            `<button class="use-api-btn" data-index="${index}" style="padding: 4px 12px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 8px; font-size: 12px;">使用</button>`
                        }
                        <button class="edit-api-btn" data-index="${index}" style="padding: 4px 12px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 8px; font-size: 12px;">编辑</button>
                        ${settings.apiConfigs.length > 1 ?
                            `<button class="delete-api-btn" data-index="${index}" style="padding: 4px 12px; background-color: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px;">删除</button>` : ''
                        }
                    </div>
                    <div style="margin-bottom: 8px;"><strong style="color: #333;">名称:</strong> <span style="color: #666;">${api.name}</span></div>
                    <div style="margin-bottom: 8px;"><strong style="color: #333;">端点:</strong> <span style="color: #666;">${api.apiEndpoint}</span></div>
                    <div style="margin-bottom: 8px;"><strong style="color: #333;">密钥:</strong> <span style="color: #666;">${api.apiKey ? '******' + api.apiKey.substring(api.apiKey.length - 4) : '未设置'}</span></div>
                    <div><strong style="color: #333;">模型:</strong> <span style="color: #666;">${api.model}</span></div>
                </div>
            `).join('');

            document.getElementById('api-list').innerHTML = apiListHtml;
            bindApiListEvents();
        }

        // 显示和隐藏面板的方法
        const show = () => {
            settingsPanel.style.display = 'flex';
            settingsPanel.style.flexDirection = 'column';
            updateSettingsPanelView();
        };

        const hide = () => {
            settingsPanel.style.display = 'none';
        };

        return {
            panel: settingsPanel,
            show: show,
            hide: hide,
            updateView: updateSettingsPanelView
        };
    }

    function createSettingsButton() {
        const settingsButton = document.createElement('div');
        settingsButton.id = 'translator-settings-button';
        settingsButton.innerHTML = '⚙️';
        settingsButton.title = '翻译设置';
        settingsButton.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 20px;
            width: 40px;
            height: 40px;
            background-color: rgba(66, 133, 244, 0.8);
            color: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 20px;
            cursor: pointer;
            z-index: 9999;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        `;

        document.body.appendChild(settingsButton);

        const settingsPanel = createSettingsPanel();

        settingsButton.addEventListener('click', function() {
            // 显示面板并设置flex布局
            settingsPanel.panel.style.display = 'flex';
            settingsPanel.panel.style.flexDirection = 'column';
            
            // 强制确保有一个有效的当前标签
            if (!settings.currentTab || (settings.currentTab !== 'general' && settings.currentTab !== 'api')) {
                settings.currentTab = 'general';
            }
            
            // 由于没有updateSettingsPanelView函数,直接更新当前标签的显示
            const generalTab = document.getElementById('general-tab');
            const apiTab = document.getElementById('api-tab');
            
            if (generalTab && apiTab) {
                generalTab.style.display = settings.currentTab === 'general' ? 'block' : 'none';
                apiTab.style.display = settings.currentTab === 'api' ? 'block' : 'none';
            }
        });

        return settingsButton;
    }

    // 创建翻译整页按钮
    function createTranslatePageButton() {
        const button = document.createElement('div');
        button.id = 'translate-page-button';
        button.innerHTML = '翻译整页';
        button.title = '翻译当前页面内容';
        button.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 70px;
            padding: 8px 12px;
            background-color: rgba(66, 133, 244, 0.8);
            color: white;
            border-radius: 20px;
            font-size: 14px;
            cursor: pointer;
            z-index: 9999;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
            display: flex;
            align-items: center;
            justify-content: center;
        `;

        document.body.appendChild(button);

        button.addEventListener('click', function () {
            if (isTranslatingFullPage) {
                alert('正在翻译中,请稍候...');
                return;
            }
            translateFullPage();
        });

        return button;
    }

    // 创建翻译进度条
    function createProgressBar() {
        const progressContainer = document.createElement('div');
        progressContainer.id = 'translation-progress-container';
        progressContainer.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 4px;
            background-color: #f3f3f3;
            z-index: 10001;
            display: none;
        `;

        const progressBar = document.createElement('div');
        progressBar.id = 'translation-progress-bar';
        progressBar.style.cssText = `
            height: 100%;
            width: 0%;
            background-color: #4285f4;
            transition: width 0.3s;
        `;

        progressContainer.appendChild(progressBar);
        document.body.appendChild(progressContainer);

        return progressContainer;
    }

    // 深度优先遍历DOM树
    function extractTextNodesFromElement(element, textSegments, depth = 0, excludeElements = null, isInReferencesSection = false, referencesSectionElement = null) {
        // 如果没有传入排除元素,使用全局的
        if (excludeElements === null) {
            excludeElements = settings.excludeSelectors ?
                Array.from(document.querySelectorAll(settings.excludeSelectors)) : [];
        }
        
        // 检查是否进入了参考文献区域
        if (element === referencesSectionElement) {
            isInReferencesSection = true;
        }

        // 如果这个元素在排除列表中,跳过
        if (excludeElements.includes(element)) {
            return;
        }

        try {
            // 只对元素节点检查样式
            if (element.nodeType === Node.ELEMENT_NODE) {
                // 检查元素是否隐藏
                const style = window.getComputedStyle(element);
                if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
                    return;
                }

                // 特殊处理参考文献条目
                // 参考文献条目通常以数字加方括号开头,如 [1], [2] 等
                if (isInReferencesSection && /^\s*\[\d+\]/.test(element.textContent)) {
                    console.log("检测到参考文献条目:", element.textContent.substring(0, 50));
                    textSegments.push({
                        text: element.textContent,
                        element: element,
                        htmlContent: element.innerHTML,
                        isReferenceItem: true,
                        isInReferencesSection: true,
                        original: element.textContent
                    });
                    return; // 参考文献条目作为整体处理,不再递归子节点
                }

                // 对于块级元素,我们在处理完所有子节点后添加换行标记
                const isBlockElement = style.display === 'block' || 
                                     style.display === 'flex' || 
                                     style.display === 'grid' || 
                                     element.tagName === 'DIV' || 
                                     element.tagName === 'P' || 
                                     element.tagName === 'SECTION' || 
                                     element.tagName === 'ARTICLE' ||
                                     element.tagName === 'LI';
                
                // 递归处理子节点
                for (let i = 0; i < element.childNodes.length; i++) {
                    extractTextNodesFromElement(element.childNodes[i], textSegments, depth + 1, excludeElements, isInReferencesSection, referencesSectionElement);
                }

                // 添加换行标记
                if (isBlockElement && element.textContent.trim() && element.childNodes.length > 0) {
                    textSegments.push({ isNewLine: true });
                }
            } else if (element.nodeType === Node.TEXT_NODE) {
                // 文本节点
                const text = element.textContent.trim();
                if (text) {
                    textSegments.push({
                        text: text,
                        node: element,
                        original: element.textContent,
                        parentElement: element.parentElement,
                        isInReferencesSection: isInReferencesSection
                    });
                }
            }
        } catch (error) {
            console.warn("处理元素时出错:", error);
        }
    }
    
    // 合并文本段落,特殊处理参考文献条目
    function mergeTextSegments(textSegments) {
        // 合并相邻文本段落,特殊处理参考文献条目
        const mergedSegments = [];
        let currentSegment = { text: '', nodes: [], isReferenceItem: false };
        let referenceItems = [];

        for (const segment of textSegments) {
            // 如果是参考文献条目,单独处理
            if (segment.isReferenceItem) {
                // 如果当前段落有内容,先保存
                if (currentSegment.text.trim()) {
                    mergedSegments.push({ ...currentSegment });
                    currentSegment = { text: '', nodes: [], isReferenceItem: false };
                }

                // 添加参考文献条目
                referenceItems.push(segment);
                mergedSegments.push({
                    text: segment.text,
                    element: segment.element,
                    htmlContent: segment.htmlContent,
                    isReferenceItem: true,
                    nodes: [{ node: segment.element, original: segment.original }]
                });

                continue;
            }

            // 如果是参考文献区域但非条目,可能需要特殊处理
            if (segment.isInReferencesSection && !segment.isNewLine) {
                // 可能属于参考文献区域的普通文本,保持段落结构
                if (currentSegment.isInReferencesSection !== true) {
                    // 如果当前段落不是参考文献区域,创建新段落
                    if (currentSegment.text.trim()) {
                        mergedSegments.push({ ...currentSegment });
                    }
                    currentSegment = {
                        text: segment.text,
                        nodes: segment.node ? [{ node: segment.node, original: segment.original }] : [],
                        isInReferencesSection: true
                    };
                } else {
                    // 属于同一参考文献区域段落,合并文本
                    currentSegment.text += (currentSegment.text ? ' ' : '') + segment.text;
                    if (segment.node) {
                        currentSegment.nodes.push({
                            node: segment.node,
                            original: segment.original,
                            parentElement: segment.parentElement
                        });
                    }
                }
                continue;
            }

            if (segment.isNewLine) {
                if (currentSegment.text.trim()) {
                    mergedSegments.push({ ...currentSegment });
                    currentSegment = { text: '', nodes: [], isReferenceItem: false };
                }
                continue;
            }

            currentSegment.text += (currentSegment.text ? ' ' : '') + segment.text;
            if (segment.node) {
                currentSegment.nodes.push({
                    node: segment.node,
                    original: segment.original,
                    parentElement: segment.parentElement
                });
            }

            // 如果当前段落已经足够长,创建新段落
            if (currentSegment.text.length >= settings.fullPageMaxSegmentLength) {
                mergedSegments.push({ ...currentSegment });
                currentSegment = { text: '', nodes: [], isReferenceItem: false };
            }
        }

        // 添加最后一个段落
        if (currentSegment.text.trim()) {
            mergedSegments.push(currentSegment);
        }

        console.log(`提取到${mergedSegments.length}个文本段落,其中参考文献条目${referenceItems.length}个`);
        return mergedSegments;
    }
    
    // 修改extractPageContent函数,使用合并函数
    function extractPageContent() {
        console.log("开始提取页面内容");
        
        // 如果启用了自动识别文章主体,尝试识别
        if (settings.detectArticleContent) {
            const rawSegments = detectMainContent();
            if (rawSegments) {
                console.log("成功识别到文章主体内容");
                return mergeTextSegments(rawSegments);
            } else {
                console.log("未能识别出文章主体,回退到常规翻译模式");
            }
        }
        
        const contentSelector = settings.fullPageTranslationSelector || 'body';
        const contentElement = document.querySelector(contentSelector);

        if (!contentElement) {
            console.error(`未找到匹配选择器的元素: ${contentSelector}`);
            return [];
        }

        // 获取所有需要排除的元素
        const excludeElements = settings.excludeSelectors ?
            Array.from(document.querySelectorAll(settings.excludeSelectors)) : [];

        // 检测参考文献区域
        const referencesElements = Array.from(document.querySelectorAll('h2, h3, h4')).filter(el =>
            el.textContent.toLowerCase().includes('reference') ||
            el.textContent.toLowerCase().includes('bibliography') ||
            el.textContent.includes('参考文献')
        );

        let isInReferencesSection = false;
        let referencesSectionElement = null;

        if (referencesElements.length > 0) {
            referencesSectionElement = referencesElements[0];
            console.log("检测到参考文献区域:", referencesSectionElement.textContent);
        }
        
        // 存储提取的文本段落
        const textSegments = [];
        
        // 深度优先遍历DOM树
        extractTextNodesFromElement(contentElement, textSegments);
        
        // 合并相邻文本段落
        return mergeTextSegments(textSegments);
    }
    
    // 识别网页中的文章主体内容
    function detectMainContent() {
        // 可能的文章主体容器选择器
        const possibleArticleSelectors = [
            'article',
            '.article', 
            '.post', 
            '.content', 
            '.post-content',
            '.article-content', 
            '.entry-content',
            '.main-content',
            'main',
            '#main',
            '#content',
            '.story',
            '[itemprop="articleBody"]',
            '[role="main"]',
            // 添加Divi主题常用的内容容器选择器
            '.et_pb_post_content',
            '.et_pb_module.et_pb_post_content',
            '.et_pb_text_inner',
            '.et_pb_post_content_0_tb_body',
            '.et_builder_inner_content',
            // 添加更多通用选择器
            '.single-content',
            '.single-post-content',
            '.page-content',
            '.post-text'
        ];
        
        // 尝试这些选择器,寻找包含最多内容的元素
        let bestElement = null;
        let maxTextLength = 0;
        
        for (const selector of possibleArticleSelectors) {
            const elements = document.querySelectorAll(selector);
            
            for (const element of elements) {
                // 计算文本内容长度
                const textLength = element.textContent.trim().length;
                
                // 如果比之前找到的更长,更新最佳元素
                if (textLength > maxTextLength) {
                    maxTextLength = textLength;
                    bestElement = element;
                }
            }
        }
        
        // 如果找到了合适的元素
        if (bestElement && maxTextLength > 300) { // 降低阈值,从500改为300个字符,更容易识别较短的文章
            console.log(`检测到文章主体: ${bestElement.tagName}${bestElement.id ? '#'+bestElement.id : ''}${bestElement.className ? '.'+bestElement.className.replace(/\s+/g, '.') : ''}`);
            
            // 获取所有需要排除的元素
            const excludeElements = settings.excludeSelectors ?
                Array.from(document.querySelectorAll(settings.excludeSelectors)) : [];
                
            // 检测参考文献区域
            const referencesElements = Array.from(bestElement.querySelectorAll('h2, h3, h4')).filter(el =>
                el.textContent.toLowerCase().includes('reference') ||
                el.textContent.toLowerCase().includes('bibliography') ||
                el.textContent.includes('参考文献')
            );
            
            let isInReferencesSection = false;
            let referencesSectionElement = null;
            
            if (referencesElements.length > 0) {
                referencesSectionElement = referencesElements[0];
                console.log("在文章主体中检测到参考文献区域:", referencesSectionElement.textContent);
            }
            
            // 存储提取的文本段落
            const textSegments = [];
            
            // 深度优先遍历DOM树
            extractTextNodesFromElement(bestElement, textSegments, 0, excludeElements, isInReferencesSection, referencesSectionElement);
            
            return textSegments.length > 0 ? textSegments : null;
        }
        
        // 尝试基于内容区域比例的检测策略
        if (!bestElement) {
            console.log("尝试使用内容区域比例检测策略");
            // 获取所有段落和文本块
            const textBlocks = Array.from(document.querySelectorAll('p, article, .post, .content, div > h1 + p, div > h2 + p'));
            
            // 按照父元素对文本块进行分组
            const contentGroups = {};
            for (const block of textBlocks) {
                if (!block.textContent.trim()) continue;
                
                // 获取所有父元素,直到body
                let parent = block.parentElement;
                while (parent && parent.tagName !== 'BODY') {
                    const key = parent.tagName + (parent.id ? '#' + parent.id : '') + 
                                (parent.className ? '.' + parent.className.replace(/\s+/g, '.') : '');
                    
                    contentGroups[key] = contentGroups[key] || { element: parent, textLength: 0 };
                    contentGroups[key].textLength += block.textContent.trim().length;
                    
                    parent = parent.parentElement;
                }
            }
            
            // 找出包含最多文本内容的容器
            let bestContentGroup = null;
            let maxGroupTextLength = 0;
            
            for (const key in contentGroups) {
                if (contentGroups[key].textLength > maxGroupTextLength) {
                    maxGroupTextLength = contentGroups[key].textLength;
                    bestContentGroup = contentGroups[key];
                }
            }
            
            if (bestContentGroup && maxGroupTextLength > 300) {
                console.log(`通过内容区域比例检测到文章主体: ${bestContentGroup.element.tagName}${bestContentGroup.element.id ? '#'+bestContentGroup.element.id : ''}${bestContentGroup.element.className ? '.'+bestContentGroup.element.className.replace(/\s+/g, '.') : ''}`);
                
                // 获取所有需要排除的元素
                const excludeElements = settings.excludeSelectors ?
                    Array.from(document.querySelectorAll(settings.excludeSelectors)) : [];
                
                // 存储提取的文本段落
                const textSegments = [];
                
                // 深度优先遍历DOM树
                extractTextNodesFromElement(bestContentGroup.element, textSegments, 0, excludeElements, false, null);
                
                return textSegments.length > 0 ? textSegments : null;
            }
        }
        
        return null;
    }

    // 翻译整个页面
    function translateFullPage() {
        if (!settings.apiKey) {
            alert('请先在设置中配置API密钥');
            const settingsPanel = document.getElementById('translator-settings-panel') || createSettingsPanel();
            settingsPanel.style.display = 'block';
            return;
        }

        // 如果当前已经在翻译中但被暂停了,则恢复翻译
        if (isTranslatingFullPage && isTranslationPaused) {
            isTranslationPaused = false;
            const pauseBtn = document.getElementById('pause-translation-button');
            if (pauseBtn) {
                pauseBtn.textContent = '暂停翻译';
                pauseBtn.title = '暂停当前的翻译任务';
            }
            // 恢复翻译,从最后翻译的段落的下一段开始
            translateNextSegment(lastTranslatedIndex + 1);
            return;
        }

        // 如果当前正在翻译且未暂停,则不做任何操作
        if (isTranslatingFullPage && !isTranslationPaused) {
            alert('正在翻译中,请稍候...');
            return;
        }

        // 开始新的翻译任务
        isTranslatingFullPage = true;
        isTranslationPaused = false;
        lastTranslatedIndex = -1;
        
        // 清除可能存在的暂停/停止按钮
        removeControlButtons();
        
        // 清除可能存在的状态提示元素
        const existingStatusElement = document.getElementById('translation-status');
        if (existingStatusElement) {
            existingStatusElement.remove();
        }
        
        // 提取页面内容
        translationSegments = extractPageContent();

        if (translationSegments.length === 0) {
            alert('未找到可翻译的内容');
            isTranslatingFullPage = false;
            return;
        }

        // 显示进度条
        const progressContainer = document.getElementById('translation-progress-container') || createProgressBar();
        const progressBar = document.getElementById('translation-progress-bar');
        progressContainer.style.display = 'block';
        progressBar.style.width = '0%';

        // 创建一个状态提示
        const statusElement = document.createElement('div');
        statusElement.id = 'translation-status';
        statusElement.style.cssText = `
            position: fixed;
            top: 10px;
            left: 50%;
            transform: translateX(-50%);
            background-color: rgba(66, 133, 244, 0.9);
            color: white;
            padding: 8px 15px;
            border-radius: 20px;
            font-size: 14px;
            z-index: 10001;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
            transition: background-color 0.3s;
            min-width: 200px;
            text-align: center;
        `;
        statusElement.textContent = `正在翻译 (0/${translationSegments.length})`;
        document.body.appendChild(statusElement);

        // 记录所有段落的原始文本,用于恢复
        originalTexts = translationSegments.map(segment => ({
            nodes: segment.nodes.map(n => ({ node: n.node, text: n.original }))
        }));

        // 创建用于切换原文/译文的按钮
        createToggleButton();
        
        // 创建暂停和停止按钮
        createControlButtons();

        // 开始翻译第一个段落
        translateNextSegment(0);
    }
    
    // 创建暂停和停止按钮
    function createControlButtons() {
        // 创建暂停按钮
        const pauseButton = document.createElement('div');
        pauseButton.id = 'pause-translation-button';
        pauseButton.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 310px;
            padding: 8px 12px;
            background-color: rgba(255, 152, 0, 0.8);
            color: white;
            border-radius: 20px;
            font-size: 14px;
            cursor: pointer;
            z-index: 9999;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        `;
        pauseButton.textContent = '暂停翻译';
        pauseButton.title = '暂停当前的翻译任务';
        document.body.appendChild(pauseButton);

        // 创建停止按钮
        const stopButton = document.createElement('div');
        stopButton.id = 'stop-translation-button';
        stopButton.style.cssText = `
            position: fixed;
            bottom: 20px;
            right: 240px;
            padding: 8px 12px;
            background-color: rgba(244, 67, 54, 0.8);
            color: white;
            border-radius: 20px;
            font-size: 14px;
            cursor: pointer;
            z-index: 9999;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
        `;
        stopButton.textContent = '停止翻译';
        stopButton.title = '停止当前的翻译任务';
        document.body.appendChild(stopButton);

        // 绑定暂停按钮事件
        pauseButton.addEventListener('click', function() {
            if (!isTranslatingFullPage) return;

            isTranslationPaused = !isTranslationPaused;
            if (isTranslationPaused) {
                pauseButton.textContent = '继续翻译';
                pauseButton.title = '继续未完成的翻译任务';
                
                // 更新状态提示
                const statusElement = document.getElementById('translation-status');
                if (statusElement) {
                    statusElement.textContent = `翻译已暂停 (${lastTranslatedIndex + 1}/${translationSegments.length})`;
                }
                
                // 显示切换按钮,允许在暂停时切换查看原文/译文
                const toggleButton = document.getElementById('toggle-translation-button');
                if (toggleButton) toggleButton.style.display = 'block';
            } else {
                pauseButton.textContent = '暂停翻译';
                pauseButton.title = '暂停当前的翻译任务';
                
                // 恢复翻译
                translateNextSegment(lastTranslatedIndex + 1);
            }
        });

        // 绑定停止按钮事件
        stopButton.addEventListener('click', function() {
            if (!isTranslatingFullPage) return;

            // 确认是否要停止翻译
            if (confirm('确定要停止翻译吗?已翻译的内容将保留。')) {
                // 停止翻译
                isTranslatingFullPage = false;
                isTranslationPaused = false;
                
                // 更新状态提示
                const statusElement = document.getElementById('translation-status');
                if (statusElement) {
                    statusElement.textContent = `翻译已停止 (${lastTranslatedIndex + 1}/${translationSegments.length})`;
                    
                    // 添加关闭按钮
                    if (!statusElement.querySelector('.close-btn')) {
                        const closeButton = document.createElement('span');
                        closeButton.className = 'close-btn';
                        closeButton.style.cssText = `
                            margin-left: 10px;
                            cursor: pointer;
                            font-weight: bold;
                        `;
                        closeButton.textContent = '×';
                        closeButton.addEventListener('click', function() {
                            statusElement.remove();
                            const progressContainer = document.getElementById('translation-progress-container');
                            if (progressContainer) progressContainer.style.display = 'none';
                        });
                        statusElement.appendChild(closeButton);
                    }
                }
                
                // 显示切换按钮
                const toggleButton = document.getElementById('toggle-translation-button');
                if (toggleButton) toggleButton.style.display = 'block';
                
                // 删除控制按钮
                removeControlButtons();
            }
        });
    }
    
    // 移除控制按钮
    function removeControlButtons() {
        const pauseButton = document.getElementById('pause-translation-button');
        if (pauseButton) pauseButton.remove();
        
        const stopButton = document.getElementById('stop-translation-button');
        if (stopButton) stopButton.remove();
    }
    
    // 创建切换按钮
    function createToggleButton() {
        // 检查是否已存在切换按钮
        let toggleButton = document.getElementById('toggle-translation-button');
        
        if (!toggleButton) {
            toggleButton = document.createElement('div');
            toggleButton.id = 'toggle-translation-button';
            toggleButton.style.cssText = `
                position: fixed;
                bottom: 20px;
                right: 180px;
                padding: 8px 12px;
                background-color: rgba(66, 133, 244, 0.8);
                color: white;
                border-radius: 20px;
                font-size: 14px;
                cursor: pointer;
                z-index: 9999;
                box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
                display: none;
            `;
            toggleButton.textContent = '查看原文';
            toggleButton.dataset.showing = 'translation';
            document.body.appendChild(toggleButton);

            // 用于跟踪当前显示状态
            let isShowingTranslation = true;

            // 创建映射,用于跟踪每个节点的翻译状态
            const nodeTranslationMap = new Map();

            toggleButton.addEventListener('click', function () {
                isShowingTranslation = !isShowingTranslation;
                toggleButton.textContent = isShowingTranslation ? '查看原文' : '查看译文';
                toggleButton.dataset.showing = isShowingTranslation ? 'translation' : 'original';

                if (isShowingTranslation) {
                    // 恢复译文
                    translationSegments.forEach((segment, index) => {
                        // 特殊处理参考文献条目
                        if (segment.isReferenceItem && segment.translation && segment.element) {
                            segment.element.innerHTML = segment.translation;
                            return;
                        }

                        if (segment.translation) {
                            if (segment.nodes.length === 1) {
                                // 单节点情况,直接应用翻译
                                const nodeInfo = segment.nodes[0];
                                if (nodeInfo.node && nodeInfo.node.nodeType === Node.TEXT_NODE) {
                                    nodeInfo.node.textContent = segment.translation;
                                    // 记录这个节点已经被翻译过
                                    nodeTranslationMap.set(nodeInfo.node, true);
                                }
                            } else {
                                // 多节点情况,使用比例分配
                                const totalOriginalLength = segment.nodes.reduce(
                                    (sum, nodeInfo) => sum + (nodeInfo.original ? nodeInfo.original.length : 0), 0);

                                if (totalOriginalLength > 0) {
                                    let startPos = 0;
                                    for (let i = 0; i < segment.nodes.length; i++) {
                                        const nodeInfo = segment.nodes[i];
                                        if (nodeInfo.node && nodeInfo.node.nodeType === Node.TEXT_NODE && nodeInfo.original) {
                                            // 计算该节点在原始文本中的比例
                                            const ratio = nodeInfo.original.length / totalOriginalLength;
                                            // 计算应该分配给该节点的翻译文本长度
                                            const chunkLength = Math.round(segment.translation.length * ratio);
                                            // 提取翻译文本的一部分
                                            let chunk = '';
                                            if (i === segment.nodes.length - 1) {
                                                // 最后一个节点,获取剩余所有文本
                                                chunk = segment.translation.substring(startPos);
                                            } else {
                                                // 非最后节点,按比例获取
                                                chunk = segment.translation.substring(startPos, startPos + chunkLength);
                                                startPos += chunkLength;
                                            }

                                            // 更新节点文本
                                            nodeInfo.node.textContent = chunk;
                                            // 记录这个节点已经被翻译过
                                            nodeTranslationMap.set(nodeInfo.node, true);
                                        }
                                    }
                                }
                            }
                        }
                    });
                } else {
                    // 恢复原文 - 使用原始数据而不是依赖当前DOM状态
                    nodeTranslationMap.clear(); // 清除翻译状态记录

                    // 先处理参考文献条目
                    translationSegments.forEach((segment) => {
                        if (segment.isReferenceItem && segment.element && segment.originalHtml) {
                            segment.element.innerHTML = segment.originalHtml;
                        }
                    });

                    // 再处理普通段落
                    originalTexts.forEach((originalSegment) => {
                        originalSegment.nodes.forEach(nodeInfo => {
                            if (nodeInfo.node && nodeInfo.node.nodeType === Node.TEXT_NODE) {
                                nodeInfo.node.textContent = nodeInfo.text;
                            }
                        });
                    });
                }
            });
        }
        
        return toggleButton;
    }

    // 添加一个专门用于翻译参考文献条目的函数
    function translateReferenceItem(referenceItem, callback) {
        if (!referenceItem || !referenceItem.text) {
            callback(null);
            return;
        }

        console.log("翻译参考文献条目:", referenceItem.text.substring(0, 50) + "...");

        // 如果有HTML内容,使用更精确的方法
        if (referenceItem.htmlContent) {
            // 提取HTML中的纯文本部分
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = referenceItem.htmlContent;

            // 递归处理HTML元素,只翻译文本节点
            function processNode(node, callback) {
                if (node.nodeType === Node.TEXT_NODE) {
                    const text = node.textContent.trim();
                    if (text && text.length > 1) {
                        // 翻译文本节点
                        translateText(text, function (result) {
                            if (result.type === 'complete' || result.type === 'stream-end') {
                                node.textContent = result.content;
                                callback(true);
                            } else {
                                // 保持原文
                                callback(false);
                            }
                        }, false);
                    } else {
                        callback(true); // 空文本,直接继续
                    }
                } else if (node.nodeType === Node.ELEMENT_NODE) {
                    // 对于元素节点,递归处理其子节点
                    const childNodes = Array.from(node.childNodes);
                    processNodeSequentially(childNodes, 0, function () {
                        callback(true);
                    });
                } else {
                    callback(true); // 其他类型节点,直接继续
                }
            }

            // 按顺序处理节点列表
            function processNodeSequentially(nodes, index, finalCallback) {
                if (index >= nodes.length) {
                    finalCallback();
                    return;
                }

                processNode(nodes[index], function (success) {
                    // 无论成功与否,继续处理下一个节点
                    setTimeout(() => processNodeSequentially(nodes, index + 1, finalCallback), 10);
                });
            }

            // 开始处理整个HTML片段
            processNodeSequentially(Array.from(tempDiv.childNodes), 0, function () {
                // 处理完成后,返回完整的翻译后HTML
                callback(tempDiv.innerHTML);
            });
        } else {
            // 如果没有HTML内容,直接翻译文本
            translateText(referenceItem.text, function (result) {
                if (result.type === 'complete' || result.type === 'stream-end') {
                    callback(result.content);
                } else {
                    callback(null);
                }
            }, false);
        }
    }

    // 创建翻译按钮
    function createTranslateButton() {
        const button = document.createElement('div');
        button.className = 'translate-button';
        button.innerHTML = '翻译';
        button.style.cssText = `
            position: absolute;
            background-color: rgba(66, 133, 244, 0.8);
            color: white;
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 14px;
            cursor: pointer;
            z-index: 9999;
            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
            opacity: 0.8;
            transition: opacity 0.2s;
        `;

        button.addEventListener('mouseover', function () {
            button.style.opacity = '1';
        });

        button.addEventListener('mouseout', function () {
            button.style.opacity = '0.8';
        });

        return button;
    }

    // 创建历史记录面板
    function createHistoryPanel() {
        const panel = document.createElement('div');
        panel.id = 'translator-history-panel';
        panel.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 600px;
            max-height: 80vh;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
            z-index: 10000;
            display: none;
            padding: 20px;
            overflow-y: auto;
        `;

        panel.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
                <h2 style="margin: 0;">翻译历史</h2>
                <div style="display: flex; gap: 10px;">
                    <button id="clear-history" style="padding: 5px 10px; color: #666;">清除历史</button>
                    <div id="close-history" style="cursor: pointer; font-size: 20px; color: #666;">×</div>
                </div>
            </div>
            <div id="history-list"></div>
        `;

        document.body.appendChild(panel);

        // 清除历史记录按钮
        document.getElementById('clear-history').addEventListener('click', function () {
            if (confirm('确定要清除所有翻译历史吗?')) {
                translationHistory = [];
                GM_setValue('translationHistory', []);
                updateHistoryList();
            }
        });

        // 关闭按钮
        document.getElementById('close-history').addEventListener('click', function () {
            panel.style.display = 'none';
        });

        return panel;
    }

    // 创建收藏夹面板
    function createFavoritesPanel() {
        const panel = document.createElement('div');
        panel.id = 'translator-favorites-panel';
        panel.style.cssText = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 600px;
            max-height: 80vh;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
            z-index: 10000;
            display: none;
            padding: 20px;
            overflow-y: auto;
        `;

        panel.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
                <h2 style="margin: 0;">收藏夹</h2>
                <div style="display: flex; gap: 10px;">
                    <button id="clear-favorites" style="padding: 5px 10px; color: #666;">清除收藏</button>
                    <div id="close-favorites" style="cursor: pointer; font-size: 20px; color: #666;">×</div>
                </div>
            </div>
            <div id="favorites-list"></div>
        `;

        document.body.appendChild(panel);

        // 清除收藏按钮
        document.getElementById('clear-favorites').addEventListener('click', function () {
            if (confirm('确定要清除所有收藏吗?')) {
                translationFavorites = [];
                GM_setValue('translationFavorites', []);
                updateFavoritesList();
            }
        });

        // 关闭按钮
        document.getElementById('close-favorites').addEventListener('click', function () {
            panel.style.display = 'none';
        });

        return panel;
    }

    // 更新历史记录列表
    function updateHistoryList() {
        const historyList = document.getElementById('history-list');
        if (!historyList) return;

        if (translationHistory.length === 0) {
            historyList.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">暂无翻译历史</div>';
            return;
        }

        // 清除之前的内容
        historyList.innerHTML = '';

        // 为每个历史记录创建DOM元素
        translationHistory.forEach((item, index) => {
            const historyItem = document.createElement('div');
            historyItem.style.cssText = 'border-bottom: 1px solid #eee; padding: 10px 0;';

            const header = document.createElement('div');
            header.style.cssText = 'display: flex; justify-content: space-between; margin-bottom: 5px;';

            const timestamp = document.createElement('span');
            timestamp.style.color = '#666';
            timestamp.textContent = item.timestamp;

            const buttons = document.createElement('div');

            const copyBtn = document.createElement('button');
            copyBtn.textContent = '复制';
            copyBtn.style.cssText = 'padding: 2px 5px; margin-right: 5px;';
            copyBtn.addEventListener('click', function () {
                copyTranslation(index);
            });

            const favoriteBtn = document.createElement('button');
            favoriteBtn.textContent = '收藏';
            favoriteBtn.style.cssText = 'padding: 2px 5px;';
            favoriteBtn.addEventListener('click', function () {
                addToFavorites(translationHistory[index]);
                favoriteBtn.textContent = '已收藏';
                favoriteBtn.disabled = true;
            });

            buttons.appendChild(copyBtn);
            buttons.appendChild(favoriteBtn);

            header.appendChild(timestamp);
            header.appendChild(buttons);

            const sourceDiv = document.createElement('div');
            sourceDiv.style.marginBottom = '5px';
            sourceDiv.innerHTML = `<strong>原文:</strong>${item.source}`;

            const translationDiv = document.createElement('div');
            translationDiv.innerHTML = `<strong>译文:</strong>${item.translation}`;

            historyItem.appendChild(header);
            historyItem.appendChild(sourceDiv);
            historyItem.appendChild(translationDiv);

            historyList.appendChild(historyItem);
        });
    }

    // 更新收藏夹列表
    function updateFavoritesList() {
        const favoritesList = document.getElementById('favorites-list');
        if (!favoritesList) return;

        if (translationFavorites.length === 0) {
            favoritesList.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">暂无收藏内容</div>';
            return;
        }

        // 清除之前的内容
        favoritesList.innerHTML = '';

        // 为每个收藏项创建DOM元素
        translationFavorites.forEach((item, index) => {
            const favoriteItem = document.createElement('div');
            favoriteItem.style.cssText = 'border-bottom: 1px solid #eee; padding: 10px 0;';

            const header = document.createElement('div');
            header.style.cssText = 'display: flex; justify-content: space-between; margin-bottom: 5px;';

            const timestamp = document.createElement('span');
            timestamp.style.color = '#666';
            timestamp.textContent = item.timestamp;

            const buttons = document.createElement('div');

            const copyBtn = document.createElement('button');
            copyBtn.textContent = '复制';
            copyBtn.style.cssText = 'padding: 2px 5px; margin-right: 5px;';
            copyBtn.addEventListener('click', function () {
                copyFavorite(index);
            });

            const deleteBtn = document.createElement('button');
            deleteBtn.textContent = '删除';
            deleteBtn.style.cssText = 'padding: 2px 5px;';
            deleteBtn.addEventListener('click', function () {
                removeFromFavorites(index);
            });

            buttons.appendChild(copyBtn);
            buttons.appendChild(deleteBtn);

            header.appendChild(timestamp);
            header.appendChild(buttons);

            const sourceDiv = document.createElement('div');
            sourceDiv.style.marginBottom = '5px';
            sourceDiv.innerHTML = `<strong>原文:</strong>${item.source}`;

            const translationDiv = document.createElement('div');
            translationDiv.style.marginBottom = '5px';
            translationDiv.innerHTML = `<strong>译文:</strong>${item.translation}`;

            const sourceUrlDiv = document.createElement('div');
            sourceUrlDiv.style.cssText = 'font-size: 12px; color: #666;';

            const sourceTitleDiv = document.createElement('div');
            sourceTitleDiv.style.marginBottom = '2px';
            sourceTitleDiv.innerHTML = '<strong>来源:</strong>';

            const sourceLink = document.createElement('a');
            sourceLink.href = item.url;
            sourceLink.target = '_blank';
            sourceLink.style.cssText = 'color: #4285f4; text-decoration: none;';
            sourceLink.textContent = item.title || item.url;

            sourceTitleDiv.appendChild(sourceLink);

            const urlDiv = document.createElement('div');
            urlDiv.style.wordBreak = 'break-all';
            urlDiv.textContent = item.url;

            sourceUrlDiv.appendChild(sourceTitleDiv);
            sourceUrlDiv.appendChild(urlDiv);

            favoriteItem.appendChild(header);
            favoriteItem.appendChild(sourceDiv);
            favoriteItem.appendChild(translationDiv);
            favoriteItem.appendChild(sourceUrlDiv);

            favoritesList.appendChild(favoriteItem);
        });
    }

    // 添加到历史记录
    function addToHistory(source, translation) {
        const timestamp = new Date().toLocaleString();
        translationHistory.unshift({ source, translation, timestamp });

        // 限制历史记录数量
        if (translationHistory.length > settings.maxHistoryItems) {
            translationHistory.pop();
        }

        GM_setValue('translationHistory', translationHistory);
        updateHistoryList();
    }

    // 添加到收藏夹
    function addToFavorites(item) {
        // 添加URL信息
        item.url = window.location.href;
        item.title = document.title;

        // 检查是否已存在
        if (!translationFavorites.some(fav => fav.source === item.source)) {
            translationFavorites.unshift(item);

            // 限制收藏数量
            if (translationFavorites.length > settings.maxFavoritesItems) {
                translationFavorites.pop();
            }

            GM_setValue('translationFavorites', translationFavorites);
            updateFavoritesList();
        }
    }

    // 从收藏夹移除
    function removeFromFavorites(index) {
        translationFavorites.splice(index, 1);
        GM_setValue('translationFavorites', translationFavorites);
        updateFavoritesList();
    }

    // 复制翻译结果
    function copyTranslation(index) {
        const item = translationHistory[index];
        if (item) {
            navigator.clipboard.writeText(item.translation).then(() => {
                alert('已复制到剪贴板!');
            });
        }
    }

    // 复制收藏的翻译
    function copyFavorite(index) {
        const item = translationFavorites[index];
        if (item) {
            navigator.clipboard.writeText(item.translation).then(() => {
                alert('已复制到剪贴板!');
            });
        }
    }

    // 注册菜单命令
    GM_registerMenuCommand('翻译整页', translateFullPage);
    GM_registerMenuCommand('查看翻译历史', function () {
        const panel = document.getElementById('translator-history-panel') || createHistoryPanel();
        panel.style.display = 'block';
        updateHistoryList();
    });
    GM_registerMenuCommand('查看收藏夹', function () {
        const panel = document.getElementById('translator-favorites-panel') || createFavoritesPanel();
        panel.style.display = 'block';
        updateFavoritesList();
    });

    // 创建翻译弹窗
    function createTranslationPopup() {
        // 主容器
        const popup = document.createElement('div');
        popup.className = 'translation-popup';
        popup.style.cssText = `
            position: absolute;
            background-color: white;
            min-width: 200px;
            max-width: 400px;
            max-height: 80vh;
            display: flex;
            flex-direction: column;
            padding: 0;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
            z-index: 10000;
            font-size: 14px;
            line-height: 1.5;
            overflow: hidden;
            user-select: none; /* 防止拖动时选中文本 */
        `;

        // ===== 顶部区域(可拖动) =====
        const header = document.createElement('div');
        header.className = 'translation-header';
        header.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 10px 15px;
            border-bottom: 1px solid #eee;
            flex-shrink: 0;
            cursor: move; /* 指示可拖动 */
            background-color: #f9f9f9; /* 轻微背景色以区分可拖动区域 */
            border-radius: 8px 8px 0 0;
            position: relative; /* 确保关闭按钮定位正确 */
        `;
        
        // 拖动提示图标
        const dragHandleIcon = document.createElement('div');
        dragHandleIcon.className = 'drag-handle-icon';
        dragHandleIcon.innerHTML = '⋮⋮';
        dragHandleIcon.style.cssText = `
            margin-right: 6px;
            color: #999;
            font-size: 10px;
            transform: rotate(90deg);
            display: inline-block;
        `;
        
        // 源语言显示区域
        const sourceLanguage = document.createElement('div');
        sourceLanguage.className = 'source-language';
        sourceLanguage.style.cssText = `
            color: #666;
            font-size: 12px;
            margin-left: 8px;
            flex-grow: 1;
        `;
        sourceLanguage.textContent = '源语言: 加载中...';
        
        // 关闭按钮
        const closeButton = document.createElement('div');
        closeButton.className = 'close-button';
        closeButton.innerHTML = '×';
        closeButton.style.cssText = `
            width: 20px;
            height: 20px;
            text-align: center;
            line-height: 20px;
            font-size: 18px;
            cursor: pointer;
            color: #666;
            background-color: white;
            border-radius: 50%;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
            margin-left: 10px;
        `;
        
        // 组装头部
        header.appendChild(dragHandleIcon);
        header.appendChild(sourceLanguage);
        header.appendChild(closeButton);
        
        // ===== 内容区域(可滚动) =====
        const contentWrapper = document.createElement('div');
        contentWrapper.className = 'content-wrapper';
        contentWrapper.style.cssText = `
            padding: 10px 15px;
            flex-grow: 1;
            overflow-y: auto;
            max-height: calc(80vh - 90px); /* 减去头部和底部的高度 */
        `;
        
        // 创建内容区域
        const content = document.createElement('div');
        content.className = 'translation-content';
        content.style.cssText = `
            white-space: pre-wrap;
        `;

        // 添加内容区域到内容包装器
        contentWrapper.appendChild(content);
        
        // ===== 底部区域 =====
        const footer = document.createElement('div');
        footer.className = 'translation-footer';
        footer.style.cssText = `
            display: flex;
            justify-content: flex-end;
            gap: 10px;
            padding: 10px 15px;
            border-top: 1px solid #eee;
            background-color: white;
            flex-shrink: 0;
        `;

        // 复制按钮
        const copyButton = document.createElement('button');
        copyButton.className = 'copy-button';
        copyButton.textContent = '复制译文';
        copyButton.style.cssText = `
            padding: 5px 10px;
            background-color: #4285f4;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
        `;

        // 收藏按钮
        const favoriteButton = document.createElement('button');
        favoriteButton.className = 'favorite-button';
        favoriteButton.textContent = '收藏';
        favoriteButton.style.cssText = `
            padding: 5px 10px;
            background-color: #fbbc05;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
        `;

        // 添加按钮到底部
        footer.appendChild(copyButton);
        footer.appendChild(favoriteButton);

        // ===== 组装整个弹窗 =====
        popup.appendChild(header);
        popup.appendChild(contentWrapper);
        popup.appendChild(footer);

        // ===== 事件处理 =====
        // 绑定事件 - 改进版
        let isDragging = false;
        let offsetX, offsetY;
        let popupRect = null;
        
        // 存储当前的鼠标事件处理函数,用于后续移除
        let mouseMoveHandler, mouseUpHandler;
        
        // 关闭按钮事件
        closeButton.addEventListener('click', function() {
            if (typeof popup.cleanup === 'function') {
                popup.cleanup();
            }
            popup.remove();
        });
        
        // 复制按钮事件
        copyButton.addEventListener('click', function() {
            const translationText = content.textContent;
            navigator.clipboard.writeText(translationText)
                .then(() => {
                    copyButton.textContent = '✓ 已复制';
                    setTimeout(() => {
                        copyButton.textContent = '复制译文';
                    }, 2000);
                })
                .catch(err => {
                    console.error('无法复制文本: ', err);
            });
        });

        // 收藏按钮事件
        favoriteButton.addEventListener('click', function() {
            const translationText = content.textContent;
            const sourceText = sourceLanguage.textContent.replace('源语言: ', '');
            
            addToFavorites({
                source: sourceText,
                translation: translationText
            });
            
            favoriteButton.textContent = '✓ 已收藏';
            setTimeout(() => {
                favoriteButton.textContent = '收藏';
            }, 2000);
        });
        
        // 鼠标按下事件 - 拖动开始
        header.addEventListener('mousedown', function(e) {
            // 如果点击的是关闭按钮,不启动拖动
            if (e.target === closeButton) return;
            
            isDragging = true;
            
            // 获取弹窗的当前位置和尺寸
            popupRect = popup.getBoundingClientRect();
            // 调整偏移量,只考虑相对于视口的位置,不考虑滚动
            offsetX = e.clientX - popupRect.left;
            offsetY = e.clientY - popupRect.top;
            
            // 添加临时样式增强拖动体验
            popup.style.transition = 'none';
            popup.style.opacity = '0.95';
            popup.style.boxShadow = '0 5px 15px rgba(0, 0, 0, 0.3)';
            document.body.style.cursor = 'move';
            
            // 防止文本选择和其他默认行为
            e.preventDefault();
            
            // 临时添加鼠标移动和释放事件处理函数
            mouseMoveHandler = handleMouseMove;
            mouseUpHandler = handleMouseUp;
            
            document.addEventListener('mousemove', mouseMoveHandler);
            document.addEventListener('mouseup', mouseUpHandler);
        });
        
        // 鼠标移动处理函数
        function handleMouseMove(e) {
            if (!isDragging) return;
            
            // 计算新位置,考虑页面滚动偏移量
            const left = e.clientX - offsetX + window.scrollX;
            const top = e.clientY - offsetY + window.scrollY;
            
            // 防止拖出窗口边界
            const windowWidth = window.innerWidth;
            const windowHeight = window.innerHeight;
            
            const maxLeft = window.scrollX + windowWidth - 100; // 保留至少100px在视口内
            const maxTop = window.scrollY + windowHeight - 50;  // 保留至少50px在视口内
            
            // 设置约束后的位置
            popup.style.left = `${Math.max(window.scrollX, Math.min(maxLeft, left))}px`;
            popup.style.top = `${Math.max(window.scrollY, Math.min(maxTop, top))}px`;
            
            // 防止事件传递给下层元素
            e.stopPropagation();
            e.preventDefault();
        }
        
        // 鼠标释放处理函数
        function handleMouseUp() {
            if (!isDragging) return;
            
            isDragging = false;
            
            // 恢复正常样式
            popup.style.opacity = '1';
            popup.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)';
            document.body.style.cursor = 'auto';
            
            // 移除临时事件处理函数
            document.removeEventListener('mousemove', mouseMoveHandler);
            document.removeEventListener('mouseup', mouseUpHandler);
        }
        
        // 清理函数 - 当弹窗被移除时调用
        function cleanup() {
            // 确保移除所有事件监听器,防止内存泄漏
            document.removeEventListener('mousemove', mouseMoveHandler);
            document.removeEventListener('mouseup', mouseUpHandler);
        }
        
        // 将清理函数和关键元素引用附加到弹窗上,方便外部访问
        popup.cleanup = cleanup;
        popup.content = content;
        popup.sourceLanguage = sourceLanguage;
        popup.contentWrapper = contentWrapper;

        return popup;
    }

    // 创建加载动画
    function createLoadingAnimation() {
        const loading = document.createElement('div');
        loading.className = 'loading-animation';
        loading.style.cssText = `
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid rgba(0, 0, 0, 0.1);
            border-radius: 50%;
            border-top-color: #4285f4;
            animation: spin 1s ease-in-out infinite;
            margin-right: 10px;
        `;

        const style = document.createElement('style');
        style.textContent = `
            @keyframes spin {
                0% { transform: rotate(0deg); }
                100% { transform: rotate(360deg); }
            }
        `;

        document.head.appendChild(style);

        return loading;
    }

    // 调用 API 进行翻译
    function translateText(text, callback, retryWithoutStreaming = false, context = null) {
        if (!settings.apiKey) {
            callback({
                type: 'error',
                content: '错误:请先设置 API 密钥'
            });
            return;
        }

        // 调试模式
        const debugMode = true;
        const debugLog = debugMode ? console.log : function () { };

        // 创建内容收集器和状态跟踪
        let collectedContent = '';
        let lastProcessedLength = 0; // 跟踪上次处理的响应长度
        let responseBuffer = ''; // 用于存储部分响应,解决跨块JSON问题

        // 确定是否使用流式响应
        const useStreaming = retryWithoutStreaming ? false : settings.useStreaming;

        // 通知回调开始处理
        if (useStreaming) {
            callback({
                type: 'stream-start',
                content: ''
            });
        }

        debugLog(`开始翻译请求,文本长度: ${text.length}, 使用流式响应: ${useStreaming}, 模型: ${settings.model}`);

        // 准备消息数组
        const messages = [
            {
                role: "system",
                content: settings.systemPrompt + " 请保持原文本的段落格式,每个段落之间应当保留一个空行。"
            }
        ];

        // 如果有上下文且启用了上下文功能,添加上下文消息
        if (settings.useTranslationContext && context && context.length > 0) {
            messages.push({
                role: "system",
                content: "以下是之前已经翻译的上下文,供你参考以保持翻译的一致性和连贯性:"
            });
            
            // 添加上下文
            context.forEach(ctx => {
                messages.push({
                    role: "user",
                    content: ctx.original
                });
                messages.push({
                    role: "assistant",
                    content: ctx.translation
                });
            });
        }

        // 添加当前要翻译的文本
        messages.push({
            role: "user",
            content: text
        });
        debugLog(messages)
        GM_xmlhttpRequest({
            method: 'POST',
            url: settings.apiEndpoint,
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${settings.apiKey}`
            },
            responseType: useStreaming ? 'stream' : '',
            timeout: 60000,
            data: JSON.stringify({
                model: settings.model,
                messages: messages,
                temperature: settings.temperature,
                stream: useStreaming,
                top_p: 1,
                frequency_penalty: 0,
                presence_penalty: 0,
                max_tokens: 4000
            }),
            onloadstart: function () {
                if (useStreaming) {
                    debugLog("流式请求已开始");
                } else {
                    debugLog("标准请求已开始");
                    debugLog(settings.temperature)
                }
            },
            onprogress: function (response) {
                if (!useStreaming) return; // 非流式模式不处理进度更新

                try {
                    // 获取完整响应文本
                    const responseText = response.responseText || '';

                    // 如果响应没变长,不处理
                    if (!responseText || responseText.length <= lastProcessedLength) {
                        return;
                    }

                    debugLog(`进度更新: 响应总长度=${responseText.length}, 上次处理位置=${lastProcessedLength}`);

                    // 获取新增内容
                    const newChunk = responseText.substring(lastProcessedLength);
                    debugLog(`接收新数据: ${newChunk.length}字节`);

                    // 更新处理位置要放在处理数据前,防止数据处理期间发生新的onprogress事件
                    lastProcessedLength = responseText.length;

                    // 追加到缓冲区并处理
                    responseBuffer += newChunk;

                    // 不同API可能有不同的流式输出格式,我们需要支持多种格式
                    // 1. OpenAI风格: "data: {\"id\":\"...\",\"choices\":[{\"delta\":{\"content\":\"文本片段\"}}]}\n"
                    // 2. 简单文本块风格: 直接是文本内容

                    let newContent = '';
                    let dataMatches = [];

                    // 尝试提取所有"data: {...}"格式的行
                    const regex = /data: ({.+?})\n/g;
                    let match;

                    // 收集所有匹配项
                    while ((match = regex.exec(responseBuffer)) !== null) {
                        dataMatches.push(match[0]);

                        try {
                            // 提取JSON部分并解析
                            const jsonStr = match[1];
                            const data = JSON.parse(jsonStr);

                            // 从JSON提取文本内容
                            if (data.choices && data.choices[0]) {
                                if (data.choices[0].delta && data.choices[0].delta.content) {
                                    // OpenAI风格的delta格式
                                    newContent += data.choices[0].delta.content;
                                } else if (data.choices[0].text) {
                                    // 有些API使用text字段
                                    newContent += data.choices[0].text;
                                } else if (data.choices[0].message && data.choices[0].message.content) {
                                    // 完整消息格式
                                    newContent += data.choices[0].message.content;
                                }
                            }
                        } catch (parseError) {
                            // 解析出错,记录但继续处理
                            debugLog(`JSON解析失败: ${parseError.message}, 内容: ${match[0].substring(0, 50)}...`);
                        }
                    }

                    // 检查是否找到了标准格式的数据行
                    if (dataMatches.length > 0) {
                        // 从缓冲区中移除已处理的部分,但保留可能不完整的最后部分
                        const lastMatchEndIndex = regex.lastIndex;
                        if (lastMatchEndIndex > 0 && lastMatchEndIndex < responseBuffer.length) {
                            responseBuffer = responseBuffer.substring(lastMatchEndIndex);
                        } else {
                            responseBuffer = '';
                        }

                        debugLog(`找到${dataMatches.length}个数据块,提取了${newContent.length}字符的内容`);
                    } else {
                        // 如果没有找到标准格式,尝试按行分割处理
                        const lines = responseBuffer.split('\n');

                        // 保留最后一行作为可能的不完整行
                        responseBuffer = lines.pop() || '';

                        // 处理每一行
                        for (const line of lines) {
                            // 尝试提取"data: "后面的内容
                            if (line.trim().startsWith('data: ')) {
                                try {
                                    const content = line.substring(6).trim();
                                    if (content === '[DONE]') {
                                        debugLog("收到流结束标记");
                                        continue;
                                    }

                                    // 尝试解析JSON
                                    const data = JSON.parse(content);
                                    if (data.choices && data.choices[0]) {
                                        if (data.choices[0].delta && data.choices[0].delta.content) {
                                            newContent += data.choices[0].delta.content;
                                        } else if (data.choices[0].text) {
                                            newContent += data.choices[0].text;
                                        } else if (data.choices[0].message && data.choices[0].message.content) {
                                            newContent += data.choices[0].message.content;
                                        }
                                    }
                                } catch (e) {
                                    // JSON解析失败,可能是普通文本或特殊格式
                                    debugLog(`处理行出错: ${e.message}, 行内容: ${line.substring(0, 50)}...`);
                                }
                            } else if (line.trim() && !line.includes('event:') && !line.includes('id:')) {
                                // 如果不是控制行且非空,可能是直接的文本内容
                                // 一些API直接发送文本而不是JSON
                                newContent += line + '\n';
                            }
                        }
                    }

                    // 如果有新内容
                    if (newContent) {
                        collectedContent += newContent;
                        debugLog(`新增内容: ${newContent.length}字符, 当前总内容: ${collectedContent.length}字符`);

                        // 发送更新
                        callback({
                            type: 'stream-progress',
                            content: collectedContent
                        });
                    } else if (dataMatches.length > 0 || responseBuffer.includes('data:')) {
                        // 找到了数据行但没有提取到内容,可能是API发送的是控制消息
                        debugLog("收到数据但未提取到新内容,可能是控制消息");
                    } else {
                        debugLog("本次更新没有提取到新内容");
                    }
                } catch (e) {
                    console.error("处理流数据错误:", e);
                    debugLog("错误详情:", e.stack);

                    // 即使出错也更新位置,防止重复处理导致死循环
                    if (response && response.responseText) {
                        lastProcessedLength = response.responseText.length;
                    }
                }
            },
            onload: function (response) {
                try {
                    // 检查HTTP状态码
                    if (response.status && response.status !== 200) {
                        // 非200状态码,记录错误但不替换原文
                        console.error(`API返回非200状态码: ${response.status}`);
                        let errorMsg = `API返回错误状态码: ${response.status}`;
                        
                        // 尝试从响应中提取更详细的错误信息
                        if (response.responseText) {
                            try {
                                const errorData = JSON.parse(response.responseText);
                                if (errorData.error) {
                                    errorMsg += ` - ${errorData.error.message || errorData.error.type || JSON.stringify(errorData.error)}`;
                                }
                            } catch (e) {
                                // 无法解析JSON,使用原始响应内容
                                if (response.responseText.length < 100) {
                                    errorMsg += ` - ${response.responseText}`;
                                }
                            }
                        }
                        
                        callback({
                            type: 'error',
                            content: errorMsg,
                            statusCode: response.status
                        });
                        return;
                    }
                    
                    // 检查是否已经收集到内容(通过流式API)
                    if (useStreaming && collectedContent) {
                        // 已收集到了内容 - 直接使用收集到的内容
                        debugLog("onload: 使用已收集的流式内容,长度:", collectedContent.length);
                        callback({
                            type: 'stream-end',
                            content: collectedContent
                        });
                        return;
                    }

                    debugLog(`onload: ${useStreaming ? '没有收集到流式内容' : '使用标准响应'}, 尝试处理完整响应`);

                    // 在流式模式下,如果没有responseText但我们仍然到达onload,这可能是一个API限制
                    if (useStreaming && (!response || typeof response.responseText !== 'string' || response.responseText.trim() === '')) {
                        // 检查是否有响应头,可能表明API连接是成功的
                        if (response && response.responseHeaders) {
                            // 尝试从缓冲区中恢复,有时onload触发时缓冲区仍有未处理的内容
                            if (responseBuffer.trim()) {
                                debugLog("onload: 从缓冲区恢复内容,尝试解析");
                                try {
                                    // 处理缓冲区中的内容
                                    let content = '';
                                    const lines = responseBuffer.split('\n').filter(line => line.trim());

                                    for (const line of lines) {
                                        if (line.startsWith('data: ') && line !== 'data: [DONE]') {
                                            try {
                                                const jsonStr = line.substring(6).trim();
                                                const data = JSON.parse(jsonStr);
                                                if (data.choices && data.choices[0]) {
                                                    if (data.choices[0].delta && data.choices[0].delta.content) {
                                                        content += data.choices[0].delta.content;
                                                    } else if (data.choices[0].message && data.choices[0].message.content) {
                                                        content += data.choices[0].message.content;
                                                    }
                                                }
                                            } catch (e) {
                                                debugLog("缓冲区解析出错:", e.message);
                                            }
                                        }
                                    }

                                    if (content) {
                                        // 找到了内容,使用它
                                        callback({
                                            type: 'complete',
                                            content: content.trim()
                                        });
                                        return;
                                    }
                                } catch (e) {
                                    debugLog("缓冲区处理失败:", e.message);
                                }
                            }

                            if (response.responseHeaders.includes("content-type:text/event-stream")) {
                                debugLog("onload: 检测到有效的SSE响应头,但无responseText。尝试使用非流式模式重试...");

                                // 自动重试:使用非流式模式
                                if (!retryWithoutStreaming) {
                                    debugLog("切换到非流式模式重试翻译请求");
                                    translateText(text, callback, true);
                                    return;
                                } else {
                                    // 如果这是重试尝试但仍然失败,则报告错误
                                    throw new Error("即使在非流式模式下,API也未能返回翻译内容。请检查API密钥和网络连接。");
                                }
                            } else {
                                // 其他内容类型,可能是API错误
                                throw new Error(`响应没有包含预期的内容。响应头: ${response.responseHeaders.substring(0, 100)}...`);
                            }
                        } else {
                            // 完全无效的响应
                            throw new Error("响应对象无效或不包含内容。请检查API端点和密钥是否正确。");
                        }
                    }

                    // 有responseText,处理它
                    const responseText = response.responseText;
                    debugLog(`获取到响应文本,长度: ${responseText.length}`);

                    // 检查是否是SSE格式(以'data: '开头)
                    if (responseText.trim().startsWith('data: ')) {
                        debugLog("检测到SSE格式响应,解析数据...");
                        // 处理SSE格式
                        const lines = responseText.split('\n');
                        let fullContent = '';
                        let processedCount = 0;

                        for (let i = 0; i < lines.length; i++) {
                            const line = lines[i].trim();
                            if (line.startsWith('data: ') && line !== 'data: [DONE]') {
                                try {
                                    // 提取JSON部分
                                    const jsonData = line.substring(6);
                                    const data = JSON.parse(jsonData);
                                    processedCount++;

                                    if (data.choices && data.choices[0]) {
                                        // 对于非流式响应中的SSE格式,提取content
                                        if (data.choices[0].delta && data.choices[0].delta.content) {
                                            fullContent += data.choices[0].delta.content;
                                        }
                                        // 支持普通响应格式
                                        else if (data.choices[0].message && data.choices[0].message.content) {
                                            fullContent += data.choices[0].message.content;
                                        }
                                        // 支持一些API的不同格式
                                        else if (data.choices[0].text) {
                                            fullContent += data.choices[0].text;
                                        }
                                    }
                                } catch (e) {
                                    console.error("处理单行SSE数据出错:", e, "行内容:", line);
                                }
                            }
                        }

                        debugLog(`解析了${processedCount}行SSE数据,提取了${fullContent.length}字符的内容`);

                        if (fullContent) {
                            callback({
                                type: 'complete',
                                content: fullContent.trim()
                            });
                            return;
                        } else {
                            throw new Error("无法从SSE响应中提取内容");
                        }
                    }

                    // 尝试作为单个JSON对象解析
                    try {
                        debugLog("尝试解析为标准JSON响应");
                        const data = JSON.parse(responseText);
                        if (data.error) {
                            callback({
                                type: 'error',
                                content: `错误:${data.error.message || JSON.stringify(data.error)}`
                            });
                        } else if (data.choices && data.choices[0]) {
                            // 提取不同格式的内容
                            let content = '';
                            if (data.choices[0].message && data.choices[0].message.content) {
                                content = data.choices[0].message.content;
                            } else if (data.choices[0].text) {
                                content = data.choices[0].text;
                            }

                            if (content) {
                                callback({
                                    type: 'complete',
                                    content: content.trim()
                                });
                            } else {
                                throw new Error("API响应中未找到内容字段");
                            }
                        } else {
                            throw new Error("API响应格式不符合预期");
                        }
                    } catch (e) {
                        // JSON解析失败,可能是纯文本响应或其他格式
                        debugLog("JSON解析失败,尝试其他格式:", e.message);

                        // 如果响应看起来像纯文本,直接使用
                        if (responseText && !responseText.startsWith('{') && !responseText.startsWith('[') && !responseText.includes('<!DOCTYPE')) {
                            debugLog("响应似乎是纯文本,直接返回");
                            callback({
                                type: 'complete',
                                content: responseText.trim()
                            });
                            return;
                        }

                        // 其他情况下,报告错误
                        throw new Error(`非标准响应格式: ${e.message}`);
                    }
                } catch (e) {
                    // 安全地获取响应预览,避免undefined错误
                    let responsePreview = "无法获取响应内容";
                    try {
                        if (response && typeof response.responseText === 'string') {
                            responsePreview = response.responseText.substring(0, 200);
                        } else if (response) {
                            // 尝试获取响应头信息作为调试参考
                            responsePreview = JSON.stringify(response).substring(0, 300);
                        }
                    } catch (previewError) {
                        responsePreview = `获取响应预览时出错: ${previewError.message}`;
                    }

                    console.error("响应处理错误:", e.message);
                    console.error("错误详情:", e.stack);
                    console.error("响应信息:", responsePreview);

                    // 给用户一些有用的建议
                    let errorMessage = e.message;
                    if (e.message.includes("API返回了成功响应") || e.message.includes("无法从SSE响应中提取内容")) {
                        errorMessage += "<br><br>建议:<br>1. 检查API密钥是否有足够的使用额度<br>2. 尝试减少翻译文本长度<br>3. <b>在设置面板中禁用流式响应</b>";
                    } else if (e.message.includes("非标准响应格式")) {
                        errorMessage += "<br><br>可能原因:<br>1. API响应格式与脚本不兼容<br>2. API返回了错误信息<br>3. API密钥可能无效";
                    }

                    callback({
                        type: 'error',
                        content: `解析响应时出错:${errorMessage}<br><br><small>响应信息: ${escapeHtml(responsePreview)}</small>`
                    });
                }
            },
            onerror: function (error) {
                console.error("API请求错误:", error);

                // 获取状态码
                const statusCode = error.status || 0;
                let errorMessage = error.statusText || '无法连接到 API';
                
                // 添加状态码到错误信息
                if (statusCode > 0) {
                    errorMessage = `(${statusCode}) ${errorMessage}`;
                }

                // 如果是流式请求失败,尝试非流式请求
                if (useStreaming && !retryWithoutStreaming) {
                    debugLog(`流式请求失败,状态码: ${statusCode},尝试使用非流式模式重试...`);
                    translateText(text, callback, true);
                    return;
                }

                callback({
                    type: 'error',
                    content: `请求错误:${errorMessage}`,
                    statusCode: statusCode
                });
            }
        });
    }

    // 辅助函数:转义HTML,防止XSS
    function escapeHtml(text) {
        return text
            .replace(/&/g, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }

    // 显示翻译结果
    async function showTranslation(text, rect) {
        // 移除之前的弹窗,确保清理事件处理函数
        const oldPopups = document.querySelectorAll('.translation-popup');
        oldPopups.forEach(popup => {
            // 如果有清理函数,调用它
            if (popup.cleanup && typeof popup.cleanup === 'function') {
                popup.cleanup();
            }
            popup.remove();
        });

        // 创建新弹窗
        const popup = createTranslationPopup();
        
        // 通过附加到弹窗上的引用获取内容元素
        const content = popup.content;
        const sourceLanguage = popup.sourceLanguage;
        const contentWrapper = popup.contentWrapper;

        // 添加加载动画
        const loadingAnimation = createLoadingAnimation();
        content.innerHTML = ''; // 清空内容
        content.appendChild(loadingAnimation);
        content.appendChild(document.createTextNode('正在翻译...'));

        // 先添加到DOM,以便获取尺寸
        document.body.appendChild(popup);

        // 获取窗口尺寸和弹窗尺寸
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        const popupWidth = popup.offsetWidth;
        const popupHeight = popup.offsetHeight;

        // 计算初始位置(选中文字的右侧)
        let left = window.scrollX + rect.right + 10; // 右侧间隔10px
        let top = window.scrollY + rect.top;

        // 检查右侧空间是否足够,如果不够则改为左侧显示
        if (left + popupWidth > window.scrollX + windowWidth) {
            left = window.scrollX + rect.left - popupWidth - 10; // 左侧间隔10px
        }

        // 如果左侧也没有足够空间,则居中显示
        if (left < window.scrollX) {
            left = window.scrollX + (windowWidth - popupWidth) / 2;
        }

        // 确保弹窗不超出视窗底部
        if (top + popupHeight > window.scrollY + windowHeight) {
            top = window.scrollY + windowHeight - popupHeight - 10; // 底部间隔10px
        }

        // 确保弹窗不超出视窗顶部
        if (top < window.scrollY) {
            top = window.scrollY + 10; // 顶部间隔10px
        }

        // 设置弹窗位置
        popup.style.left = `${left}px`;
        popup.style.top = `${top}px`;

        // 检测语言并翻译
        if (settings.autoDetectLanguage) {
            try {
                const language = await detectLanguage(text);
                sourceLanguage.textContent = `源语言: ${language}`;
                
                // 显示原文(如果启用)
                if (settings.showSourceLanguage) {
                    // 创建源文本元素
                    const sourceText = document.createElement('div');
                    sourceText.style.cssText = `
                        margin-bottom: 10px;
                        padding: 5px;
                        background-color: #f8f9fa;
                        border-radius: 4px;
                        font-size: 13px;
                        color: #666;
                    `;
                    sourceText.textContent = text;
                    
                    // 在内容前添加源文本
                    contentWrapper.insertBefore(sourceText, content);
                }
                
                // 翻译文本
                translateText(text, result => {
                    // 清除加载动画和加载文本
                content.innerHTML = '';
                    
                    // 确保结果正确显示
                    if (typeof result === 'object') {
                        if (result.type === 'error') {
                            content.textContent = `错误: ${result.content}`;
                        } else if (result.type === 'complete' || result.type === 'stream-end') {
                            content.textContent = result.content;
                            // 添加到历史记录
                            addToHistory(text, result.content);
                        } else if (result.content) {
                            content.textContent = result.content;
                        } else {
                            content.textContent = '无法解析翻译结果';
                            console.error('未能正确解析翻译结果', result);
                        }
                    } else if (typeof result === 'string') {
                        content.textContent = result;
                    } else {
                        content.textContent = '翻译过程发生错误';
                        console.error('翻译回调收到意外类型的结果', result);
                    }
                });
            } catch (error) {
                console.error('语言检测失败:', error);
                sourceLanguage.textContent = '源语言: 检测失败';
                // 继续翻译流程
                translateText(text, result => {
                    // ... 与上面相同的翻译处理逻辑 ...
                });
            }
        } else {
            sourceLanguage.textContent = '源语言: 未检测';
            
            // 显示原文(如果启用)
            if (settings.showSourceLanguage) {
                // 创建源文本元素
                const sourceText = document.createElement('div');
                sourceText.style.cssText = `
                    margin-bottom: 10px;
                    padding: 5px;
                    background-color: #f8f9fa;
                    border-radius: 4px;
                    font-size: 13px;
                    color: #666;
                `;
                sourceText.textContent = text;
                
                // 在内容前添加源文本
                contentWrapper.insertBefore(sourceText, content);
            }
            
            // 翻译文本
            translateText(text, result => {
                // 清除加载动画和加载文本
                content.innerHTML = '';
                
                // 确保结果正确显示
                if (typeof result === 'object') {
                    if (result.type === 'error') {
                        content.textContent = `错误: ${result.content}`;
                    } else if (result.type === 'complete' || result.type === 'stream-end') {
                        content.textContent = result.content;
                // 添加到历史记录
                addToHistory(text, result.content);
                    } else if (result.content) {
                        content.textContent = result.content;
                    } else {
                        content.textContent = '无法解析翻译结果';
                        console.error('未能正确解析翻译结果', result);
                    }
                } else if (typeof result === 'string') {
                    content.textContent = result;
                } else {
                    content.textContent = '翻译过程发生错误';
                    console.error('翻译回调收到意外类型的结果', result);
                }
            });
        }

        // 将选择的文本保存为全局变量,用于收藏功能
        lastSelectedText = text;
    }

    // 监听选择事件
    document.addEventListener('mouseup', function (e) {
        // 如果点击的是翻译按钮或翻译弹窗,不处理
        if (e.target.classList.contains('translate-button') ||
            e.target.closest('.translate-button') ||
            e.target.classList.contains('translation-popup') ||
            e.target.closest('.translation-popup')) {
            return;
        }

        const selection = window.getSelection();
        const selectedText = selection.toString().trim();

        // 清除之前的翻译按钮
        if (activeTranslateButton) {
            activeTranslateButton.remove();
            activeTranslateButton = null;
        }

        if (selectedText.length > 0) {
            const range = selection.getRangeAt(0);
            const rect = range.getBoundingClientRect();

            // 保存最后选择的文本和位置
            lastSelectedText = selectedText;
            lastSelectionRect = {
                top: rect.top,
                left: rect.left,
                bottom: rect.bottom,
                right: rect.right
            };

            const translateButton = createTranslateButton();
            translateButton.style.top = `${window.scrollY + rect.bottom + 5}px`;
            translateButton.style.left = `${window.scrollX + rect.right - 50}px`;

            translateButton.addEventListener('click', function (event) {
                event.stopPropagation();
                event.preventDefault();

                // 显示翻译
                showTranslation(lastSelectedText, lastSelectionRect);
            });

            document.body.appendChild(translateButton);
            activeTranslateButton = translateButton;
        }
    });

    // 在初始化时创建UI组件
    function initUI() {
        createSettingsButton();
        createTranslatePageButton();
        createProgressBar();
        
    }

    // 初始化UI
    initUI();
    
    // 重试失败的翻译
    function retryFailedTranslations() {
        // 确认有段落需要翻译
        if (!translationSegments || translationSegments.length === 0) {
            alert('没有找到需要重试的翻译段落');
            return;
        }
        
        // 收集失败项
        const failedSegments = [];
        for (let i = 0; i < translationSegments.length; i++) {
            if (translationSegments[i].error) {
                failedSegments.push(i);
            }
        }
        
        if (failedSegments.length === 0) {
            alert('没有找到失败的翻译段落');
            return;
        }
        
        // 确认是否重试
        if (!confirm(`找到${failedSegments.length}个失败的翻译段落,是否重试?`)) {
            return;
        }
        
        // 更新状态
        const statusElement = document.getElementById('translation-status');
        if (statusElement) {
            statusElement.textContent = `正在重试失败的翻译 (0/${failedSegments.length})`;
            
            // 移除之前的错误摘要
            const oldSummary = statusElement.querySelector('.error-summary');
            if (oldSummary) oldSummary.remove();
        }
        
        // 重置错误计数
        translationSegments.errorCount = 0;
        
        // 开始重试
        isTranslatingFullPage = true;
        isTranslationPaused = false;
        
        // 创建控制按钮
        createControlButtons();
        
        // 递归重试
        function retryNext(index) {
            if (index >= failedSegments.length) {
                // 重试完成
                if (statusElement) {
                    const newErrors = translationSegments.errorCount || 0;
                    statusElement.textContent = `重试完成 (${failedSegments.length}/${failedSegments.length})${newErrors > 0 ? ` (仍有${newErrors}个错误)` : ''}`;
                }
                isTranslatingFullPage = false;
                return;
            }
            
            // 如果暂停,不继续
            if (isTranslationPaused || !isTranslatingFullPage) {
                return;
            }
            
            // 更新状态
            if (statusElement) {
                statusElement.textContent = `正在重试失败的翻译 (${index + 1}/${failedSegments.length})`;
            }
            
            // 获取当前要重试的段落索引
            const segmentIndex = failedSegments[index];
            
            // 清除之前的错误标记
            if (translationSegments[segmentIndex].nodes && translationSegments[segmentIndex].nodes.length > 0) {
                const nodeInfo = translationSegments[segmentIndex].nodes[0];
                if (nodeInfo.node && nodeInfo.node.parentElement) {
                    const errorMark = nodeInfo.node.parentElement.querySelector('.translation-error-mark');
                    if (errorMark) errorMark.remove();
                }
            }
            
            // 清除错误状态
            delete translationSegments[segmentIndex].error;
            
            // 翻译该段落
            translateText(translationSegments[segmentIndex].text, function (result) {
                if (result.type === 'complete' || result.type === 'stream-end') {
                    // 翻译成功,更新
                    translationSegments[segmentIndex].translation = result.content;
                    
                    // 更新DOM
                    if (translationSegments[segmentIndex].nodes && translationSegments[segmentIndex].nodes.length > 0) {
                        // 复用现有逻辑更新DOM
                        if (translationSegments[segmentIndex].nodes.length === 1) {
                            const nodeInfo = translationSegments[segmentIndex].nodes[0];
                            if (nodeInfo.node && nodeInfo.node.nodeType === Node.TEXT_NODE) {
                                nodeInfo.node.textContent = result.content;
                                if (nodeInfo.node.parentElement) {
                                    nodeInfo.node.parentElement.style.fontWeight = 'inherit';
                                    nodeInfo.node.parentElement.dataset.translated = 'true';
                                }
                            }
                        } else {
                            // 复杂节点结构的处理略过,会在前面代码相同逻辑处理
                        }
                    }
                    
                    // 继续下一个
                    setTimeout(() => retryNext(index + 1), 50);
                } else if (result.type === 'error') {
                    // 仍然出错
                    console.error(`重试段落 ${segmentIndex + 1} 翻译失败:`, result.content);
                    translationSegments[segmentIndex].error = result.content;
                    
                    // 错误计数
                    translationSegments.errorCount = (translationSegments.errorCount || 0) + 1;
                    
                    // 添加错误标记
                    if (translationSegments[segmentIndex].nodes && translationSegments[segmentIndex].nodes.length > 0) {
                        const nodeInfo = translationSegments[segmentIndex].nodes[0];
                        if (nodeInfo.node && nodeInfo.node.parentElement) {
                            // 在段落旁创建错误标记
                            const errorMark = document.createElement('span');
                            errorMark.className = 'translation-error-mark';
                            errorMark.innerHTML = '⚠️';
                            errorMark.title = `翻译失败: ${result.content}`;
                            errorMark.style.cssText = `
                                color: #ff4d4f;
                                cursor: pointer;
                                margin-left: 5px;
                                font-size: 16px;
                            `;
                            errorMark.addEventListener('click', function() {
                                alert(`翻译错误: ${result.content}`);
                            });
                            
                            nodeInfo.node.parentElement.appendChild(errorMark);
                            
                            // 确保不修改原文内容,防止错误码替换原文
                            if (nodeInfo.original && nodeInfo.node.nodeType === Node.TEXT_NODE) {
                                if (nodeInfo.node.textContent !== nodeInfo.original) {
                                    nodeInfo.node.textContent = nodeInfo.original;
                                }
                            }
                        }
                    }
                    
                    // 继续下一个
                    setTimeout(() => retryNext(index + 1), 50);
                }
            }, false);
        }
        
        // 开始重试第一个
        retryNext(0);
    }

    // 递归翻译段落
    let translatedCount = 0;
    // 添加一些全局错误处理和减速变量
    let consecutiveErrors = 0;
    let translationDelay = 50; // 初始延迟时间(ms)
    
    function translateNextSegment(index) {
        // 如果已暂停,不继续翻译
        if (isTranslationPaused) {
            return;
        }
        
        // 记录最后翻译的索引
        lastTranslatedIndex = index - 1;
        
        // 获取进度条和状态元素
        const progressBar = document.getElementById('translation-progress-bar');
        const statusElement = document.getElementById('translation-status');
        
        if (index >= translationSegments.length) {
            // 全部翻译完成
            if (progressBar) progressBar.style.width = '100%';
            
            // 获取错误统计
            const totalErrors = translationSegments.errorCount || 0;
            const errorInfo = totalErrors > 0 ? ` (${totalErrors}个错误)` : '';
            
            if (statusElement) {
                statusElement.textContent = `翻译完成 (${translationSegments.length}/${translationSegments.length})${errorInfo}`;
                
                // 如果有错误,添加错误摘要信息
                if (totalErrors > 0) {
                    // 移除之前的错误警告(如果有)
                    const oldWarning = statusElement.querySelector('.error-warning');
                    if (oldWarning) oldWarning.remove();
                    
                    const errorSummary = document.createElement('div');
                    errorSummary.className = 'error-summary';
                    errorSummary.style.cssText = `
                        margin-top: 10px;
                        color: #ff4d4f;
                        font-size: 13px;
                        padding: 8px;
                        background-color: rgba(255, 77, 79, 0.1);
                        border-radius: 4px;
                    `;
                    
                    // 创建错误摘要内容
                    let summaryText = `翻译过程中遇到了${totalErrors}个错误。`;
                    
                    // 添加解决建议
                    if (totalErrors > 5) {
                        summaryText += `可能原因:<br>
                        1. API密钥额度不足或API限制<br>
                        2. 网络连接不稳定<br>
                        3. 翻译内容过长或API不兼容<br><br>
                        建议:<br>
                        · 检查API设置和密钥<br>
                        · 在设置中禁用流式响应<br>
                        · 尝试使用不同的API提供商`;
                    }
                    
                    errorSummary.innerHTML = summaryText;
                    statusElement.appendChild(errorSummary);
                    
                    // 添加重试错误项按钮
                    const retryButton = document.createElement('button');
                    retryButton.textContent = '重试失败项';
                    retryButton.style.cssText = `
                        margin-top: 10px;
                        padding: 5px 10px;
                        background-color: #ff4d4f;
                        color: white;
                        border: none;
                        border-radius: 4px;
                        cursor: pointer;
                    `;
                    retryButton.addEventListener('click', function() {
                        retryFailedTranslations();
                    });
                    errorSummary.appendChild(retryButton);
                }
            }

            // 添加一个关闭按钮
            if (statusElement && !statusElement.querySelector('.close-btn')) {
                const closeButton = document.createElement('span');
                closeButton.className = 'close-btn';
                closeButton.style.cssText = `
                    margin-left: 10px;
                    cursor: pointer;
                    font-weight: bold;
                `;
                closeButton.textContent = '×';
                closeButton.addEventListener('click', function () {
                    statusElement.remove();
                    const progressContainer = document.getElementById('translation-progress-container');
                    if (progressContainer) progressContainer.style.display = 'none';
                });
                statusElement.appendChild(closeButton);
            }

            // 显示切换按钮
            const toggleButton = document.getElementById('toggle-translation-button');
            if (toggleButton) toggleButton.style.display = 'block';
            
            // 移除控制按钮
            removeControlButtons();

            isTranslatingFullPage = false;
            return;
        }

        // 更新进度
        const progress = Math.round((index / translationSegments.length) * 100);
        if (progressBar) progressBar.style.width = `${progress}%`;
        if (statusElement) statusElement.textContent = `正在翻译 (${index}/${translationSegments.length})`;

        // 如果段落文本为空,直接跳到下一个
        if (!translationSegments[index].text.trim()) {
            translateNextSegment(index + 1);
            return;
        }

        // 获取上下文
        let context = [];
        if (settings.useTranslationContext && settings.contextSize > 0) {
            // 从当前段落往前获取已翻译的段落作为上下文
            for (let i = index - 1; i >= 0 && context.length < settings.contextSize; i--) {
                if (translationSegments[i] && translationSegments[i].translation) {
                    context.unshift({
                        original: translationSegments[i].text,
                        translation: translationSegments[i].translation
                    });
                }
            }
        }

        // 处理参考文献条目 - 特殊处理以保留格式
        if (translationSegments[index].isReferenceItem) {
            translateReferenceItem(translationSegments[index], function (translatedHtml) {
                if (translatedHtml) {
                    // 保存翻译结果
                    translationSegments[index].translation = translatedHtml;

                    // 保存原始HTML以便切换回来
                    if (!translationSegments[index].originalHtml && translationSegments[index].element) {
                        translationSegments[index].originalHtml = translationSegments[index].element.innerHTML;
                    }

                    // 更新DOM显示翻译结果
                    if (translationSegments[index].element) {
                        // 将翻译后的HTML设置到元素中
                        translationSegments[index].element.innerHTML = translatedHtml;
                    }

                    // 更新最后翻译的索引
                    lastTranslatedIndex = index;
                    
                    // 继续翻译下一个段落
                    setTimeout(() => translateNextSegment(index + 1), 50);
                } else {
                    // 翻译失败时继续下一个
                    console.error(`参考文献条目 ${index + 1} 翻译失败`);
                    
                    // 更新最后翻译的索引
                    lastTranslatedIndex = index;
                    
                    setTimeout(() => translateNextSegment(index + 1), 50);
                }
            });
            return;
        }

        // 常规段落翻译
        translateText(translationSegments[index].text, function (result) {
            // 如果已暂停或停止,不处理翻译结果
            if (isTranslationPaused || !isTranslatingFullPage) {
                return;
            }
            
            if (result.type === 'complete' || result.type === 'stream-end') {
                // 翻译成功
                translatedCount++;
                translationSegments[index].translation = result.content;

                // 更新DOM中的文本,保留原始样式
                if (translationSegments[index].nodes && translationSegments[index].nodes.length > 0) {
                    // 使用更智能的方式分配翻译结果
                    if (translationSegments[index].nodes.length === 1) {
                        // 只有一个节点的简单情况
                        const nodeInfo = translationSegments[index].nodes[0];
                        if (nodeInfo.node && nodeInfo.node.nodeType === Node.TEXT_NODE) {
                            nodeInfo.node.textContent = result.content;
                            
                        }
                    } else {
                        // 多个节点的情况,尝试保留原始结构
                        // 计算原始内容中每个节点文本的比例
                        const totalOriginalLength = translationSegments[index].nodes.reduce(
                            (sum, nodeInfo) => sum + (nodeInfo.original ? nodeInfo.original.length : 0), 0);

                        if (totalOriginalLength > 0) {
                            // 按照原始文本长度比例分配翻译后的文本
                            let startPos = 0;
                            for (let i = 0; i < translationSegments[index].nodes.length; i++) {
                                const nodeInfo = translationSegments[index].nodes[i];
                                if (nodeInfo.node && nodeInfo.node.nodeType === Node.TEXT_NODE && nodeInfo.original) {
                                    // 计算该节点在原始文本中的比例
                                    const ratio = nodeInfo.original.length / totalOriginalLength;
                                    // 计算应该分配给该节点的翻译文本长度
                                    const chunkLength = Math.round(result.content.length * ratio);
                                    // 提取翻译文本的一部分
                                    let chunk = '';
                                    if (i === translationSegments[index].nodes.length - 1) {
                                        // 最后一个节点,获取剩余所有文本
                                        chunk = result.content.substring(startPos);
                                    } else {
                                        // 非最后节点,按比例获取
                                        chunk = result.content.substring(startPos, startPos + chunkLength);
                                        startPos += chunkLength;
                                    }
                                    // 更新节点文本
                                    nodeInfo.node.textContent = chunk;
                                   
                                }
                            }
                        } else {
                            // 回退方案:如果无法计算比例,则将所有文本放在第一个节点
                            let foundFirstNode = false;
                            for (let i = 0; i < translationSegments[index].nodes.length; i++) {
                                const nodeInfo = translationSegments[index].nodes[i];
                                if (nodeInfo.node && nodeInfo.node.nodeType === Node.TEXT_NODE) {
                                    if (!foundFirstNode) {
                                        nodeInfo.node.textContent = result.content;
                                        foundFirstNode = true;
                                    } else {
                                        nodeInfo.node.textContent = '';
                                    }
                                }
                            }
                        }
                    }
                }
                
                // 更新最后翻译的索引
                lastTranslatedIndex = index;
                
                // 重置连续错误计数,因为成功了一次
                consecutiveErrors = 0;
                
                // 如果之前增加了延迟,且现在连续成功,则尝试逐步恢复
                if (translationDelay > 50 && translatedCount % 5 === 0) {
                    // 逐步减少延迟,但不低于初始值
                    translationDelay = Math.max(50, translationDelay * 0.8);
                    console.log(`连续翻译成功,减少延迟至${translationDelay}ms`);
                    
                    // 更新延迟信息显示
                    if (statusElement && statusElement.querySelector('.delay-info')) {
                        statusElement.querySelector('.delay-info').textContent = `已自动调整延迟至${Math.round(translationDelay)}ms`;
                        
                        // 如果延迟已经降回正常,移除通知并恢复颜色
                        if (translationDelay <= 60) {
                            statusElement.querySelector('.delay-info').remove();
                            statusElement.style.backgroundColor = 'rgba(66, 133, 244, 0.9)';
                        }
                    }
                }

                // 继续下一个段落
                setTimeout(() => translateNextSegment(index + 1), translationDelay);
            } else if (result.type === 'error') {
                // 翻译出错,记录错误并继续下一个
                console.error(`段落 ${index + 1} 翻译失败:`, result.content);
                translationSegments[index].error = result.content;
                
                // 更新最后翻译的索引
                lastTranslatedIndex = index;
                
                // 错误计数
                translationSegments.errorCount = (translationSegments.errorCount || 0) + 1;
                consecutiveErrors++;
                
                // 如果连续错误过多,自动增加延迟
                if (consecutiveErrors >= 3) {
                    // 增加延迟,但最大不超过2秒
                    translationDelay = Math.min(2000, translationDelay * 1.5);
                    console.log(`检测到连续错误,自动增加翻译延迟至${translationDelay}ms`);
                    
                    // 更新状态显示
                    if (statusElement && !statusElement.querySelector('.delay-info')) {
                        const delayInfo = document.createElement('div');
                        delayInfo.className = 'delay-info';
                        delayInfo.style.cssText = `
                            font-size: 12px;
                            margin-top: 5px;
                        `;
                        delayInfo.textContent = `已自动增加延迟至${translationDelay}ms以减轻API负载`;
                        statusElement.appendChild(delayInfo);
                    } else if (statusElement && statusElement.querySelector('.delay-info')) {
                        statusElement.querySelector('.delay-info').textContent = `已自动增加延迟至${translationDelay}ms以减轻API负载`;
                    }
                    
                    // 改变状态颜色提示错误
                    statusElement.style.backgroundColor = 'rgba(255, 152, 0, 0.9)';
                }
                
                // 显示错误提示标记在段落旁
                if (translationSegments[index].nodes && translationSegments[index].nodes.length > 0) {
                    const nodeInfo = translationSegments[index].nodes[0];
                    if (nodeInfo.node && nodeInfo.node.parentElement) {
                        // 在段落旁创建错误标记
                        const errorMark = document.createElement('span');
                        errorMark.className = 'translation-error-mark';
                        errorMark.innerHTML = '⚠️';
                        errorMark.title = `翻译失败: ${result.content}`;
                        errorMark.style.cssText = `
                            color: #ff4d4f;
                            cursor: pointer;
                            margin-left: 5px;
                            font-size: 16px;
                        `;
                        errorMark.addEventListener('click', function() {
                            alert(`翻译错误: ${result.content}`);
                        });
                        
                        nodeInfo.node.parentElement.appendChild(errorMark);
                        
                        // 重要:确保不修改原文内容,防止错误码替换原文
                        // 如果有通过错误处理设置了节点文本,恢复原始文本
                        if (nodeInfo.original && nodeInfo.node.nodeType === Node.TEXT_NODE) {
                            if (nodeInfo.node.textContent !== nodeInfo.original) {
                                nodeInfo.node.textContent = nodeInfo.original;
                            }
                        }
                    }
                }
                
                // 更新状态面板显示总体进度和错误信息
                if (statusElement) {
                    const totalErrors = translationSegments.errorCount;
                    const errorInfo = totalErrors > 0 ? ` (${totalErrors}个错误)` : '';
                    statusElement.textContent = `正在翻译 (${index + 1}/${translationSegments.length})${errorInfo}`;
                    
                    // 如果错误超过阈值,添加暂停建议
                    if (totalErrors > 5 && !statusElement.querySelector('.error-warning')) {
                        const warningElement = document.createElement('div');
                        warningElement.className = 'error-warning';
                        warningElement.style.cssText = `
                            margin-top: 5px;
                            color: #ff4d4f;
                            font-size: 12px;
                        `;
                        warningElement.textContent = `检测到多处翻译错误,可能是API限制或网络问题。考虑暂停翻译后再继续。`;
                        statusElement.appendChild(warningElement);
                    }
                }

                // 继续下一个段落
                setTimeout(() => translateNextSegment(index + 1), translationDelay);
            }
        }, false, context);  // 添加context参数
    }
})();