Greasy Fork

Greasy Fork is available in English.

大模型中文翻译助手

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

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

您需要先安装一款用户脚本管理器扩展,例如 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.4
// @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: true, // 是否显示源语言
        autoDetectLanguage: true, // 是否自动检测语言
        detectArticleContent: true, // 是否自动识别文章主体内容
        fullPageTranslationSelector: 'body', // 整页翻译时的选择器
        fullPageMaxSegmentLength: 2000, // 整页翻译时的最大分段长度
        excludeSelectors: 'script, style, noscript, iframe, img, svg, canvas, [role="banner"], [role="navigation"]', // 翻译时排除的元素
        apiConfigs: [ // 多API配置
            {
                name: 'DeepSeek',
                apiEndpoint: 'https://api.deepseek.com/v1/chat/completions',
                apiKey: '',
                model: 'deepseek-chat',
            }
        ],
        currentApiIndex: 0, // 当前使用的API索引
    };

    // 初始化设置
    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) {
        // 简单的语言检测逻辑
        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)) return '中文';
        if (englishRegex.test(text)) return '英语';
        if (japaneseRegex.test(text)) return '日语';
        if (koreanRegex.test(text)) return '韩语';
        return '未知';
    }

    // 创建设置面板
    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;
            padding: 20px;
            background-color: white;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
            z-index: 10000;
            display: none;
            max-height: 90vh;
            overflow-y: auto;
        `;

        // 创建Tab栏
        const tabsHtml = `
            <div class="settings-tabs" style="margin-bottom: 20px; border-bottom: 1px solid #eee;">
                <div class="tab-buttons" style="display: flex; margin-bottom: -1px;">
                    <button id="general-tab-btn" class="tab-btn active" style="padding: 8px 15px; background: none; border: 1px solid #eee; border-bottom: none; margin-right: 5px; cursor: pointer; border-radius: 4px 4px 0 0; background-color: ${settings.currentTab === 'general' ? '#f0f0f0' : 'white'};">常规设置</button>
                    <button id="api-tab-btn" class="tab-btn" style="padding: 8px 15px; background: none; border: 1px solid #eee; border-bottom: none; cursor: pointer; border-radius: 4px 4px 0 0; background-color: ${settings.currentTab === 'api' ? '#f0f0f0' : 'white'};">API 管理</button>
                </div>
            </div>
        `;

        // 常规设置Tab内容
        const generalTabHtml = `
            <div id="general-tab" class="tab-content" style="display: ${settings.currentTab === 'general' ? 'block' : 'none'};">
                <h2 style="margin-top: 0;">翻译设置</h2>
                <div style="margin-bottom: 15px;">
                    <label for="systemPrompt">系统提示词:</label>
                    <textarea id="systemPrompt" style="width: 100%; height: 80px; padding: 5px; margin-top: 5px;">${settings.systemPrompt}</textarea>
                </div>
                <div style="margin-bottom: 15px;">
                    <label for="temperature">随机性(Temperature)</label>
                    <div style="display: flex; align-items: center; margin-top: 5px;">
                        <input type="range" id="temperature" min="0" max="1" step="0.1" value="${settings.temperature}" style="flex-grow: 1;">
                        <span id="temperature-value" style="margin-left: 10px; min-width: 30px; text-align: center;">${settings.temperature}</span>
                    </div>
                    <div style="font-size: 12px; color: #666; margin-top: 5px;">
                        值越低翻译越准确,值越高结果越具有创意性。翻译任务建议使用较低的值。
                    </div>
                </div>
                <div style="margin-bottom: 15px;">
                    <label style="display: flex; align-items: center;">
                        <input type="checkbox" id="useStreaming" ${settings.useStreaming ? 'checked' : ''} style="margin-right: 8px;">
                        启用流式响应(实时显示翻译结果)
                    </label>
                    <div style="font-size: 12px; color: #666; margin-top: 5px;">
                        如果遇到翻译失败问题,可以尝试关闭此选项
                    </div>
                </div>
                <div style="margin-bottom: 15px;">
                    <label style="display: flex; align-items: center;">
                        <input type="checkbox" id="detectArticleContent" ${settings.detectArticleContent ? 'checked' : ''} style="margin-right: 8px;">
                        自动识别文章主体内容
                    </label>
                    <div style="font-size: 12px; color: #666; margin-top: 5px;">
                        启用后将尝试自动识别网页中的文章主体,只翻译主要内容。如识别失败将回退为常规翻译
                    </div>
                </div>
                <div style="margin-bottom: 15px;">
                    <label for="fullPageTranslationSelector">整页翻译选择器:</label>
                    <input type="text" id="fullPageTranslationSelector" style="width: 100%; padding: 5px; margin-top: 5px;" value="${settings.fullPageTranslationSelector}">
                    <div style="font-size: 12px; color: #666; margin-top: 5px;">
                        CSS选择器,用于指定翻译哪些区域的内容
                    </div>
                </div>
                <div style="margin-bottom: 15px;">
                    <label for="excludeSelectors">排除翻译的元素:</label>
                    <input type="text" id="excludeSelectors" style="width: 100%; padding: 5px; margin-top: 5px;" value="${settings.excludeSelectors}">
                    <div style="font-size: 12px; color: #666; margin-top: 5px;">
                        CSS选择器,指定要排除翻译的元素
                    </div>
                </div>
            </div>
        `;

        // API管理Tab内容
        let apiListHtml = '';
        settings.apiConfigs.forEach((api, index) => {
            apiListHtml += `
                <div class="api-item" style="margin-bottom: 15px; padding: 10px; border: 1px solid #eee; border-radius: 4px; position: relative; ${index === settings.currentApiIndex ? 'background-color: #f0f8ff;' : ''}">
                    <div style="position: absolute; top: 10px; right: 10px;">
                        ${index === settings.currentApiIndex ?
                    '<span style="color: #4CAF50; font-weight: bold;">✓ 当前使用</span>' :
                    `<button class="use-api-btn" data-index="${index}" style="padding: 3px 8px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 5px;">使用</button>`
                }
                        <button class="edit-api-btn" data-index="${index}" style="padding: 3px 8px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 5px;">编辑</button>
                        ${settings.apiConfigs.length > 1 ?
                    `<button class="delete-api-btn" data-index="${index}" style="padding: 3px 8px; background-color: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer;">删除</button>` : ''
                }
                    </div>
                    <div style="margin-bottom: 5px;"><strong>名称:</strong> ${api.name}</div>
                    <div style="margin-bottom: 5px;"><strong>端点:</strong> ${api.apiEndpoint}</div>
                    <div style="margin-bottom: 5px;"><strong>密钥:</strong> ${api.apiKey ? '******' + api.apiKey.substring(api.apiKey.length - 4) : '未设置'}</div>
                    <div><strong>模型:</strong> ${api.model}</div>
                </div>
            `;
        });

        const apiTabHtml = `
            <div id="api-tab" class="tab-content" style="display: ${settings.currentTab === 'api' ? 'block' : 'none'};">
                <h2 style="margin-top: 0; margin-bottom: 15px;">API 管理</h2>
                <div style="margin-bottom: 20px;">
                    <button id="add-api-btn" style="padding: 8px 15px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; width: 100%;">+ 添加新 API</button>
                </div>
                <div id="api-list">
                    ${apiListHtml}
                </div>
            </div>
        `;

        // 编辑API的表单
        const apiFormHtml = `
            <div id="api-form" style="display: none;">
                <h2 id="api-form-title" style="margin-top: 0;">添加 API</h2>
                <input type="hidden" id="api-form-index" value="-1">
                <div style="margin-bottom: 15px;">
                    <label for="api-name">API 名称:</label>
                    <input type="text" id="api-name" style="width: 100%; padding: 5px; margin-top: 5px;" placeholder="例如:OpenAI、Azure、DeepSeek">
                </div>
                <div style="margin-bottom: 15px;">
                    <label for="api-endpoint">API 端点:</label>
                    <input type="text" id="api-endpoint" style="width: 100%; padding: 5px; margin-top: 5px;" placeholder="例如:https://api.openai.com/v1/chat/completions">
                </div>
                <div style="margin-bottom: 15px;">
                    <label for="api-key">API 密钥:</label>
                    <input type="password" id="api-key" style="width: 100%; padding: 5px; margin-top: 5px;" placeholder="输入您的API密钥">
                    <div style="font-size: 12px; color: #666; margin-top: 5px;">
                        编辑现有API时,如不需要修改密钥请留空
                    </div>
                </div>
                <div style="margin-bottom: 15px;">
                    <label for="api-model">模型名称:</label>
                    <input type="text" id="api-model" style="width: 100%; padding: 5px; margin-top: 5px;" placeholder="例如:gpt-3.5-turbo">
                </div>
                <div style="display: flex; justify-content: flex-end; gap: 10px;">
                    <button id="cancel-api-form" style="padding: 8px 15px;">取消</button>
                    <button id="save-api-form" style="padding: 8px 15px; background-color: #4285f4; color: white; border: none; border-radius: 4px;">保存</button>
                </div>
            </div>
        `;

        const footerHtml = `
            <div style="display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px;">
                <button id="cancel-settings" style="padding: 8px 15px;">取消</button>
                <button id="save-settings" style="padding: 8px 15px; background-color: #4285f4; color: white; border: none; border-radius: 4px;">保存</button>
            </div>
        `;

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

        // 添加温度滑块的实时更新
        const temperatureSlider = document.getElementById('temperature');
        const temperatureValue = document.getElementById('temperature-value');
        temperatureSlider.addEventListener('input', function () {
            temperatureValue.textContent = this.value;
        });

        // Tab切换逻辑
        document.getElementById('general-tab-btn').addEventListener('click', function () {
            document.getElementById('general-tab').style.display = 'block';
            document.getElementById('api-tab').style.display = 'none';
            document.getElementById('api-form').style.display = 'none';
            document.getElementById('general-tab-btn').style.backgroundColor = '#f0f0f0';
            document.getElementById('api-tab-btn').style.backgroundColor = 'white';
            settings.currentTab = 'general';
        });

        document.getElementById('api-tab-btn').addEventListener('click', function () {
            document.getElementById('general-tab').style.display = 'none';
            document.getElementById('api-tab').style.display = 'block';
            document.getElementById('api-form').style.display = 'none';
            document.getElementById('general-tab-btn').style.backgroundColor = 'white';
            document.getElementById('api-tab-btn').style.backgroundColor = '#f0f0f0';
            settings.currentTab = 'api';
        });

        // 添加新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-key').placeholder = '输入您的API密钥';
            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 name = document.getElementById('api-name').value.trim();
            const endpoint = document.getElementById('api-endpoint').value.trim();
            const apiKey = document.getElementById('api-key').value.trim();
            const model = document.getElementById('api-model').value.trim();
            const index = parseInt(document.getElementById('api-form-index').value);

            if (!name || !endpoint || !model) {
                alert('请填写所有必填字段:名称、端点和模型');
                return;
            }

            if (index >= 0) {
                // 编辑现有API
                settings.apiConfigs[index] = {
                    name: name,
                    apiEndpoint: endpoint,
                    apiKey: apiKey || settings.apiConfigs[index].apiKey,
                    model: model
                };
            } else {
                // 添加新API
                settings.apiConfigs.push({
                    name: name,
                    apiEndpoint: endpoint,
                    apiKey: apiKey,
                    model: model
                });
            }

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

        // API列表的按钮事件(编辑、删除、使用)
        document.addEventListener('click', function (e) {
            // 编辑API
            if (e.target.classList.contains('edit-api-btn')) {
                const index = parseInt(e.target.getAttribute('data-index'));
                const api = settings.apiConfigs[index];

                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 = index;
                document.getElementById('api-name').value = api.name;
                document.getElementById('api-endpoint').value = api.apiEndpoint;
                document.getElementById('api-key').value = ''; // 出于安全考虑,不回显密钥
                document.getElementById('api-key').placeholder = '不修改请留空 (当前已保存密钥)';
                document.getElementById('api-model').value = api.model;
            }

            // 删除API
            if (e.target.classList.contains('delete-api-btn')) {
                const index = parseInt(e.target.getAttribute('data-index'));
                if (confirm(`确定要删除 "${settings.apiConfigs[index].name}" 吗?`)) {
                    settings.apiConfigs.splice(index, 1);

                    // 如果删除的是当前选中的API,则切换到第一个API
                    if (index === settings.currentApiIndex) {
                        settings.currentApiIndex = 0;
                        syncApiSettings();
                    } else if (index < settings.currentApiIndex) {
                        // 如果删除的是当前选中API之前的API,调整索引
                        settings.currentApiIndex--;
                    }

                    updateApiList();
                }
            }

            // 切换使用的API
            if (e.target.classList.contains('use-api-btn')) {
                const index = parseInt(e.target.getAttribute('data-index'));
                settings.currentApiIndex = index;
                syncApiSettings();
                updateApiList();
            }
        });

        // 更新API列表UI
        function updateApiList() {
            const apiList = document.getElementById('api-list');
            if (!apiList) return;

            let apiListHtml = '';
            settings.apiConfigs.forEach((api, index) => {
                apiListHtml += `
                    <div class="api-item" style="margin-bottom: 15px; padding: 10px; border: 1px solid #eee; border-radius: 4px; position: relative; ${index === settings.currentApiIndex ? 'background-color: #f0f8ff;' : ''}">
                        <div style="position: absolute; top: 10px; right: 10px;">
                            ${index === settings.currentApiIndex ?
                        '<span style="color: #4CAF50; font-weight: bold;">✓ 当前使用</span>' :
                        `<button class="use-api-btn" data-index="${index}" style="padding: 3px 8px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 5px;">使用</button>`
                    }
                            <button class="edit-api-btn" data-index="${index}" style="padding: 3px 8px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer; margin-right: 5px;">编辑</button>
                            ${settings.apiConfigs.length > 1 ?
                        `<button class="delete-api-btn" data-index="${index}" style="padding: 3px 8px; background-color: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer;">删除</button>` : ''
                    }
                        </div>
                        <div style="margin-bottom: 5px;"><strong>名称:</strong> ${api.name}</div>
                        <div style="margin-bottom: 5px;"><strong>端点:</strong> ${api.apiEndpoint}</div>
                        <div style="margin-bottom: 5px;"><strong>密钥:</strong> ${api.apiKey ? '******' + api.apiKey.substring(api.apiKey.length - 4) : '未设置'}</div>
                        <div><strong>模型:</strong> ${api.model}</div>
                    </div>
                `;
            });

            apiList.innerHTML = apiListHtml;
        }

        // 保存设置
        document.getElementById('save-settings').addEventListener('click', function () {
            settings = {
                ...settings,
                systemPrompt: document.getElementById('systemPrompt').value,
                useStreaming: document.getElementById('useStreaming').checked,
                detectArticleContent: document.getElementById('detectArticleContent').checked,
                temperature: parseFloat(document.getElementById('temperature').value),
                fullPageTranslationSelector: document.getElementById('fullPageTranslationSelector').value,
                excludeSelectors: document.getElementById('excludeSelectors').value
            };

            // 同步当前API设置
            syncApiSettings();

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

        // 取消设置
        document.getElementById('cancel-settings').addEventListener('click', function () {
            settingsPanel.style.display = 'none';
        });

        return settingsPanel;
    }

    // 创建设置按钮
    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 () {
            settingsPanel.style.display = 'block';

            // 默认显示常规设置标签
            if (!settings.currentTab) {
                settings.currentTab = 'general';
                document.getElementById('general-tab').style.display = 'block';
                document.getElementById('api-tab').style.display = 'none';
                document.getElementById('general-tab-btn').style.backgroundColor = '#f0f0f0';
                document.getElementById('api-tab-btn').style.backgroundColor = 'white';
            } else if (settings.currentTab === 'general') {
                document.getElementById('general-tab').style.display = 'block';
                document.getElementById('api-tab').style.display = 'none';
                document.getElementById('general-tab-btn').style.backgroundColor = '#f0f0f0';
                document.getElementById('api-tab-btn').style.backgroundColor = 'white';
            } else if (settings.currentTab === 'api') {
                document.getElementById('general-tab').style.display = 'none';
                document.getElementById('api-tab').style.display = 'block';
                document.getElementById('general-tab-btn').style.backgroundColor = 'white';
                document.getElementById('api-tab-btn').style.backgroundColor = '#f0f0f0';
            }
        });

        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;
            overflow-y: auto;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
            z-index: 10000;
            font-size: 14px;
            line-height: 1.5;
        `;

        const header = document.createElement('div');
        header.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 10px;
            padding-bottom: 5px;
            border-bottom: 1px solid #eee;
        `;

        const sourceLanguage = document.createElement('div');
        sourceLanguage.className = 'source-language';
        sourceLanguage.style.color = '#666';
        sourceLanguage.style.fontSize = '12px';

        const closeButton = document.createElement('div');
        closeButton.innerHTML = '×';
        closeButton.style.cssText = `
            font-size: 18px;
            cursor: pointer;
            color: #666;
        `;

        const content = document.createElement('div');
        content.className = 'translation-content';
        content.style.marginTop = '5px';
        content.style.whiteSpace = 'pre-wrap';
       

        const footer = document.createElement('div');
        footer.style.cssText = `
            display: flex;
            justify-content: flex-end;
            gap: 10px;
            margin-top: 10px;
            padding-top: 5px;
            border-top: 1px solid #eee;
        `;

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

        const favoriteButton = document.createElement('button');
        favoriteButton.textContent = '收藏';
        favoriteButton.style.cssText = `
            padding: 5px 10px;
            background-color: #f8f9fa;
            color: #666;
            border: 1px solid #ddd;
            border-radius: 4px;
            cursor: pointer;
        `;

        header.appendChild(sourceLanguage);
        header.appendChild(closeButton);
        footer.appendChild(copyButton);
        footer.appendChild(favoriteButton);

        popup.appendChild(header);
        popup.appendChild(content);
        popup.appendChild(footer);

        closeButton.addEventListener('click', function () {
            document.body.removeChild(popup);
        });

        copyButton.addEventListener('click', function () {
            navigator.clipboard.writeText(content.textContent).then(() => {
                alert('已复制到剪贴板!');
            });
        });

        favoriteButton.addEventListener('click', function () {
            addToFavorites({
                source: lastSelectedText,
                translation: content.textContent,
                timestamp: new Date().toLocaleString()
            });
            favoriteButton.textContent = '已收藏';
            favoriteButton.disabled = true;
        });

        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) {
        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}`);

        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: [
                    {
                        role: "system",
                        content: settings.systemPrompt + " 请保持原文本的段落格式,每个段落之间应当保留一个空行。"
                    },
                    {
                        role: "user",
                        content: text
                    }
                ],
                temperature: settings.temperature,  // 使用用户设置的temperature值
                stream: useStreaming,  // 根据设置决定是否使用流式响应
                // 一些API提供者可能需要额外参数或不同的参数名
                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;");
    }

    // 显示翻译结果
    function showTranslation(text, rect) {
        // 移除之前的弹窗
        const oldPopups = document.querySelectorAll('.translation-popup');
        oldPopups.forEach(popup => popup.remove());

        const popup = createTranslationPopup();
        const content = popup.querySelector('.translation-content');

        // 先添加到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;
        }

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

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

        // 显示加载动画
        content.innerHTML = '';
        const loading = createLoadingAnimation();
        content.appendChild(loading);
        content.appendChild(document.createTextNode('正在翻译...'));

        // 光标元素
        const cursor = document.createElement('span');
        cursor.className = 'typing-cursor';
        cursor.textContent = '▌';
        cursor.style.animation = 'blink 1s step-end infinite';

        // 添加光标样式
        const cursorStyle = document.createElement('style');
        cursorStyle.textContent = `
            @keyframes blink {
                0%, 100% { opacity: 1; }
                50% { opacity: 0; }
            }
        `;
        document.head.appendChild(cursorStyle);

        console.log("开始翻译:", text.substring(0, 50) + "...");

        // 检测源语言
        if (settings.autoDetectLanguage) {
            const sourceLanguage = detectLanguage(text);
            popup.querySelector('.source-language').textContent = `源语言:${sourceLanguage}`;
        }

        // 进行翻译
        translateText(text, function (result) {
            console.log("收到翻译结果类型:", result.type, "内容长度:", result.content ? result.content.length : 0);
            if (result.type === 'stream-start') {
                // 清除加载动画,准备接收流式内容
                content.innerHTML = '';
                content.appendChild(cursor);
            }
            else if (result.type === 'stream-progress') {
                // 更新内容,保持光标在末尾
                const formattedResult = result.content.replace(/\n\n+/g, '<br><br>').replace(/\n/g, '<br>');
                content.innerHTML = formattedResult;
                content.appendChild(cursor);
            }
            else if (result.type === 'stream-end' || result.type === 'complete') {
                // 最终内容,移除光标
                const formattedResult = result.content.replace(/\n\n+/g, '<br><br>').replace(/\n/g, '<br>');
                content.innerHTML = formattedResult;
                content.dataset.translated = 'true';
                content.className = 'translation-content translated-text';
                console.log("翻译完成");

                // 添加到历史记录
                addToHistory(text, result.content);
            }
            else if (result.type === 'error') {
                // 显示错误
                content.innerHTML = `<span style="color: red;">${result.content}</span>`;
                console.error("翻译出错:", result.content);
            }
        });
    }

    // 监听选择事件
    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;
        }

        // 处理参考文献条目 - 特殊处理以保留格式
        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); // 使用非流式翻译,避免更新DOM过于频繁
    }
})();