Greasy Fork

Greasy Fork is available in English.

AI网页内容智能总结助手

网页内容智能总结,支持自定义API和提示词

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

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         AI Page Summarizer Pro
// @name:zh-CN   AI网页内容智能总结助手
// @namespace    http://tampermonkey.net/
// @version      0.9.9.6
// @description  网页内容智能总结,支持自定义API和提示词
// @description:zh-CN  网页内容智能总结,支持自定义API和提示词
// @author       Your Name
// @match        *://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// @grant        GM_addStyle
// @grant        GM.xmlHttpRequest
// @grant        GM.setValue
// @grant        GM.getValue
// @grant        GM.registerMenuCommand
// @grant        GM.addStyle
// @grant        window.fetch
// @grant        window.localStorage
// @connect      api.openai.com
// @connect      *
// @require      https://cdn.jsdelivr.net/npm/[email protected]/marked.min.js
// @run-at       document-start
// @noframes
// @license      MIT
// @compatible   chrome
// @compatible   firefox
// @compatible   edge
// @compatible   opera
// @compatible   safari
// @compatible   android
// ==/UserScript==

(function() {
    'use strict';

    // 添加全局错误处理
    window.addEventListener('error', function(event) {
        console.error('脚本错误:', event.error);
        if (event.error && event.error.stack) {
            console.error('错误堆栈:', event.error.stack);
        }
    });

    window.addEventListener('unhandledrejection', function(event) {
        console.error('未处理的Promise错误:', event.reason);
    });

    // 兼容性检查
    const browserSupport = {
        hasGM: typeof GM !== 'undefined',
        hasGMFunctions: typeof GM_getValue !== 'undefined',
        hasLocalStorage: (function() {
            try {
                localStorage.setItem('test', 'test');
                localStorage.removeItem('test');
                return true;
            } catch (e) {
                return false;
            }
        })(),
        hasBackdropFilter: (function() {
            const el = document.createElement('div');
            return typeof el.style.backdropFilter !== 'undefined' || 
                   typeof el.style.webkitBackdropFilter !== 'undefined';
        })(),
        isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
        isSafari: /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
    };

    // 兼容性处理层
    const scriptHandler = {
        // 存储值
        setValue: async function(key, value) {
            try {
                if (browserSupport.hasGMFunctions) {
                    GM_setValue(key, value);
                    return true;
                } else if (browserSupport.hasGM && GM.setValue) {
                    await GM.setValue(key, value);
                    return true;
                } else if (browserSupport.hasLocalStorage) {
                    localStorage.setItem('ws_' + key, JSON.stringify(value));
                    return true;
                }
                return false;
            } catch (error) {
                console.error('存储值失败:', error);
                return false;
            }
        },
        
        // 获取值
        getValue: async function(key, defaultValue) {
            try {
                if (browserSupport.hasGMFunctions) {
                    return GM_getValue(key, defaultValue);
                } else if (browserSupport.hasGM && GM.getValue) {
                    return await GM.getValue(key, defaultValue);
                } else if (browserSupport.hasLocalStorage) {
                    const value = localStorage.getItem('ws_' + key);
                    return value ? JSON.parse(value) : defaultValue;
                }
                return defaultValue;
            } catch (error) {
                console.error('获取值失败:', error);
                return defaultValue;
            }
        },
        
        // HTTP请求
        xmlHttpRequest: function(details) {
            return new Promise((resolve, reject) => {
                const handleResponse = (response) => {
                    resolve(response);
                };

                const handleError = (error) => {
                    reject(new Error('请求错误: ' + error.message));
                };

                if (browserSupport.hasGMFunctions && typeof GM_xmlhttpRequest !== 'undefined') {
                    GM_xmlhttpRequest({
                        ...details,
                        onload: handleResponse,
                        onerror: handleError,
                        ontimeout: details.ontimeout
                    });
                } else if (browserSupport.hasGM && typeof GM !== 'undefined' && GM.xmlHttpRequest) {
                    GM.xmlHttpRequest({
                        ...details,
                        onload: handleResponse,
                        onerror: handleError,
                        ontimeout: details.ontimeout
                    });
                } else {
                    fetch(details.url, {
                        method: details.method,
                        headers: details.headers,
                        body: details.data,
                        mode: 'cors',
                        credentials: 'omit'
                    })
                    .then(async response => {
                        const text = await response.text();
                        handleResponse({
                            status: response.status,
                            responseText: text,
                            responseHeaders: [...response.headers].join('\n')
                        });
                    })
                    .catch(handleError);
                }
            }).then(response => {
                if (details.onload) {
                    details.onload(response);
                }
                return response;
            }).catch(error => {
                if (details.onerror) {
                    details.onerror(error);
                }
                throw error;
            });
        },
        
        // 注册菜单命令
        registerMenuCommand: function(name, fn) {
            try {
                if (browserSupport.hasGMFunctions) {
                    GM_registerMenuCommand(name, fn);
                    return true;
                } else if (browserSupport.hasGM && GM.registerMenuCommand) {
                    GM.registerMenuCommand(name, fn);
                    return true;
                }
                return false;
            } catch (error) {
                console.log('注册菜单命令失败:', error);
                return false;
            }
        },
        
        // 添加样式
        addStyle: function(css) {
            try {
                if (browserSupport.hasGMFunctions) {
                    GM_addStyle(css);
                    return true;
                } else if (browserSupport.hasGM && GM.addStyle) {
                    GM.addStyle(css);
                    return true;
                } else {
                    const style = document.createElement('style');
                    style.textContent = css;
                    document.head.appendChild(style);
                    return true;
                }
            } catch (error) {
                console.error('添加样式失败:', error);
                return false;
            }
        }
    };

    // 配置项
    let config = {
        apiUrl: 'https://api.openai.com/v1/chat/completions',
        apiKey: '',
        model: 'gpt-3.5-turbo',
        theme: 'light',
        prompt: `You are a professional content summarizer in chinese. Your task is to create a clear, concise, and well-structured summary of the webpage content. Follow these guidelines:

1. Output Format:
   - Use ## for main sections
   - Use bullet points (•) for key points and details
   - Use bold for important terms
   - Use blockquotes for notable quotes

2. Content Structure:
   ## 核心观点
   • Key points here...

   ## 关键信息
   • Important details here...

   ## 市场情绪
   • Market sentiment here...

   ## 专家观点
   • Expert opinions here...

   ## 总结
   • Final summary here...

3. Writing Style:
   - Clear and concise language
   - Professional tone
   - Logical flow
   - Easy to understand
   - Focus on essential information

4. Important Rules:
   - DO NOT show your reasoning process
   - DO NOT include meta-commentary
   - DO NOT explain your methodology
   - DO NOT use phrases like "this summary shows" or "the content indicates"
   - Start directly with the content summary
   - Make sure bullet points (•) are in the same line with text
   - Use ## for main section headers

Remember: Focus on delivering the information directly without any meta-analysis or explanation of your process.`,
        iconPosition: { y: 20 },
        shortcut: 'option+a',
        summaryWindowPositioned: false  // 添加窗口位置状态跟踪
    };

    // 初始化配置
    async function initConfig() {
        config.apiUrl = await scriptHandler.getValue('apiUrl', config.apiUrl);
        config.apiKey = await scriptHandler.getValue('apiKey', config.apiKey);
        config.model = await scriptHandler.getValue('model', config.model);
        config.prompt = await scriptHandler.getValue('prompt', config.prompt);
        config.iconPosition = await scriptHandler.getValue('iconPosition', config.iconPosition);
        config.shortcut = await scriptHandler.getValue('shortcut', config.shortcut);
        config.theme = await scriptHandler.getValue('theme', config.theme);
        config.summaryWindowPositioned = await scriptHandler.getValue('summaryWindowPositioned', false);
    }

    // DOM 元素引用
    const elements = {
        icon: null,
        container: null,
        settings: null,
        backdrop: null
    };

    // 全局变量用于判断是否已经监听了键盘事件
    let keyboardListenerActive = false;

    // 拖拽功能
    function makeDraggable(element) {
        let isDragging = false;
        let startX, startY, startLeft, startTop;
        
        // 添加位置信息以便拖动
        if (element.style.position !== 'fixed') {
            element.style.position = 'fixed';
        }
        
        // 确保元素有初始位置
        if (!element.style.bottom || !element.style.right) {
            element.style.bottom = '20px';
            element.style.right = '20px';
        }
        
        // 鼠标/触摸开始事件
        function handleStart(e) {
            isDragging = true;
            
            // 计算起始位置
            const rect = element.getBoundingClientRect();
            
            // 将位置从right/bottom转换为left/top以便计算
            const computedStyle = window.getComputedStyle(element);
            const right = parseInt(computedStyle.right || '0');
            const bottom = parseInt(computedStyle.bottom || '0');
            
            startLeft = window.innerWidth - right - rect.width;
            startTop = window.innerHeight - bottom - rect.height;
            
            // 记录鼠标/触摸起始位置
            if (e.type === 'touchstart') {
                startX = e.touches[0].clientX;
                startY = e.touches[0].clientY;
            } else {
                startX = e.clientX;
                startY = e.clientY;
                e.preventDefault(); // 防止选中文本
            }
            
            // 添加移动和结束事件监听
            if (e.type === 'touchstart') {
                document.addEventListener('touchmove', handleMove, { passive: false });
                document.addEventListener('touchend', handleEnd);
            } else {
                document.addEventListener('mousemove', handleMove);
                document.addEventListener('mouseup', handleEnd);
            }
            
            // 设置拖动中的样式
            element.style.transition = 'none';
            element.style.opacity = '1';
        }
        
        // 鼠标/触摸移动事件
        function handleMove(e) {
            if (!isDragging) return;
            
            let moveX, moveY;
            if (e.type === 'touchmove') {
                moveX = e.touches[0].clientX - startX;
                moveY = e.touches[0].clientY - startY;
                e.preventDefault(); // 防止页面滚动
            } else {
                moveX = e.clientX - startX;
                moveY = e.clientY - startY;
            }
            
            // 计算新位置
            let newLeft = startLeft + moveX;
            let newTop = startTop + moveY;
            
            // 边界检查
            newLeft = Math.max(0, Math.min(window.innerWidth - element.offsetWidth, newLeft));
            newTop = Math.max(0, Math.min(window.innerHeight - element.offsetHeight, newTop));
            
            // 更新位置 (使用left/top)
            element.style.left = `${newLeft}px`;
            element.style.top = `${newTop}px`;
            
            // 清除right/bottom,避免冲突
            element.style.right = '';
            element.style.bottom = '';
        }
        
        // 鼠标/触摸结束事件
        function handleEnd() {
            if (!isDragging) return;
            isDragging = false;
            
            // 移除事件监听
            document.removeEventListener('mousemove', handleMove);
            document.removeEventListener('mouseup', handleEnd);
            document.removeEventListener('touchmove', handleMove);
            document.removeEventListener('touchend', handleEnd);
            
            // 保存新位置
            const rect = element.getBoundingClientRect();
            const newX = rect.left;
            const newY = rect.top;
            
            // 转换回right/bottom定位
            const right = window.innerWidth - newX - rect.width;
            const bottom = window.innerHeight - newY - rect.height;
            
            // 设置新位置,恢复transition
            element.style.left = '';
            element.style.top = '';
            element.style.right = `${right}px`;
            element.style.bottom = `${bottom}px`;
            element.style.transition = 'opacity 0.3s ease';
            
            // 如果不是在悬停状态,恢复默认透明度
            if (!element.matches(':hover')) {
                element.style.opacity = '0.8';
            }
            
            // 保存位置到配置
            config.iconPosition = { x: newX, y: newY };
            saveConfig();
        }
        
        // 添加事件监听
        element.addEventListener('mousedown', handleStart);
        element.addEventListener('touchstart', handleStart, { passive: false });
    }

    // 显示提示消息
    function showToast(message) {
        const toast = document.createElement('div');
        toast.textContent = message;
        
        const baseStyle = `
            position: fixed;
            left: 50%;
            transform: translateX(-50%);
            background: #4CAF50;
            color: white;
            padding: ${browserSupport.isMobile ? '12px 24px' : '10px 20px'};
            border-radius: 4px;
            z-index: 1000001;
            font-size: ${browserSupport.isMobile ? '16px' : '14px'};
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
            text-align: center;
            max-width: ${browserSupport.isMobile ? '90%' : '300px'};
            word-break: break-word;
        `;
        
        // 在移动设备上显示在底部,否则显示在顶部
        const position = browserSupport.isMobile ? 
            'bottom: 80px;' : 
            'top: 20px;';
        
        toast.style.cssText = baseStyle + position;
        
        document.body.appendChild(toast);
        setTimeout(() => {
            toast.style.opacity = '0';
            toast.style.transition = 'opacity 0.3s ease';
            setTimeout(() => toast.remove(), 300);
        }, 2000);
    }

    // 快捷键处理
    const keyManager = {
        setup() {
            try {
                // 移除旧的监听器
                if (keyboardListenerActive) {
                    document.removeEventListener('keydown', this._handleKeyDown);
                }

                // 添加新的监听器
                this._handleKeyDown = (e) => {
                    // 忽略输入框中的按键
                    if (e.target.tagName === 'INPUT' || 
                        e.target.tagName === 'TEXTAREA' || 
                        e.target.isContentEditable ||
                        e.target.getAttribute('role') === 'textbox') {
                        return;
                    }

                    // 解析配置的快捷键
                    const shortcutParts = config.shortcut.toLowerCase().split('+');
                    
                    // 获取主键(非修饰键)
                    const mainKey = shortcutParts.filter(part => 
                        !['alt', 'option', 'ctrl', 'control', 'shift', 'cmd', 'command', 'meta']
                        .includes(part)
                    )[0] || 'a';
                    
                    // 检查所需的修饰键
                    const needAlt = shortcutParts.some(p => p === 'alt' || p === 'option');
                    const needCtrl = shortcutParts.some(p => p === 'ctrl' || p === 'control');
                    const needShift = shortcutParts.some(p => p === 'shift');
                    const needMeta = shortcutParts.some(p => p === 'cmd' || p === 'command' || p === 'meta');
                    
                    // 检查按键是否匹配
                    const isMainKeyMatched = 
                        e.key.toLowerCase() === mainKey || 
                        e.code.toLowerCase() === 'key' + mainKey ||
                        e.keyCode === mainKey.toUpperCase().charCodeAt(0);
                        
                    // 检查修饰键是否匹配
                    const modifiersMatch = 
                        e.altKey === needAlt && 
                        e.ctrlKey === needCtrl && 
                        e.shiftKey === needShift && 
                        e.metaKey === needMeta;
                    
                    if (isMainKeyMatched && modifiersMatch) {
                        console.log('快捷键触发成功:', config.shortcut);
                        e.preventDefault();
                        e.stopPropagation();
                        showSummary();
                        return false;
                    }
                };
                
                // 使用捕获阶段来确保我们能先捕获到事件
                document.addEventListener('keydown', this._handleKeyDown, true);
                keyboardListenerActive = true;
                
                // 设置全局访问方法
                window.activateSummary = showSummary;
                
                console.log('快捷键已设置:', config.shortcut);
                return true;
            } catch (error) {
                console.error('设置快捷键失败:', error);
                return false;
            }
        }
    };

    // 等待页面加载完成
    function waitForPageLoad() {
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initializeScript);
        } else {
            initializeScript();
        }
    }

    // 初始化脚本
    async function initializeScript() {
        try {
            // 等待marked库加载
            await waitForMarked();
            // 初始化配置
            await initConfig();
            // 添加全局样式
            addGlobalStyles();
            // 创建图标
            createIcon();
            // 设置快捷键
            keyManager.setup();
            // 注册菜单命令
            registerMenuCommands();
            
            console.log('AI Page Summarizer Pro 初始化完成');
        } catch (error) {
            console.error('初始化失败:', error);
        }
    }

    // 等待marked库加载
    function waitForMarked() {
        return new Promise((resolve) => {
            if (window.marked) {
                window.marked.setOptions({ breaks: true, gfm: true });
                resolve();
            } else {
                const checkMarked = setInterval(() => {
                    if (window.marked) {
                        clearInterval(checkMarked);
                        window.marked.setOptions({ breaks: true, gfm: true });
                        resolve();
                    }
                }, 100);
                // 10秒后超时
                setTimeout(() => {
                    clearInterval(checkMarked);
                    console.warn('marked库加载超时,继续初始化');
                    resolve();
                }, 10000);
            }
        });
    }

    // 添加全局样式
    function addGlobalStyles() {
        const css = `
            #website-summary-icon * {
                box-sizing: border-box !important;
                margin: 0 !important;
                padding: 0 !important;
            }
            #website-summary-icon span {
                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif !important;
                line-height: 1 !important;
            }
        `;
        scriptHandler.addStyle(css);
    }

    // 创建图标
    function createIcon() {
        // 检查是否已存在图标
        const existingIcon = document.getElementById('website-summary-icon');
        if (existingIcon) {
            existingIcon.remove();
        }

        // 创建图标元素
        const icon = document.createElement('div');
        icon.id = 'website-summary-icon';
        icon.innerHTML = '💡';
        icon.style.cssText = `
            position: fixed;
            z-index: 2147483647 !important;
            bottom: 20px;
            right: 20px;
            width: auto !important;
            height: auto !important;
            padding: 8px !important;
            font-size: ${browserSupport.isMobile ? '20px' : '24px'} !important;
            line-height: 1 !important;
            cursor: pointer !important;
            user-select: none !important;
            -webkit-user-select: none !important;
            visibility: visible !important;
            opacity: 0.8;
            transition: opacity 0.3s ease !important;
            border-radius: 8px !important;
            box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1) !important;
        `;

        // 添加鼠标悬停效果
        icon.addEventListener('mouseover', () => {
            icon.style.opacity = '1';
        });

        icon.addEventListener('mouseout', () => {
            icon.style.opacity = '0.8';
        });

        // 添加点击事件
        icon.addEventListener('click', async (e) => {
            e.preventDefault();
            e.stopPropagation();
            await showSummary();
        });

        // 修改右键菜单处理方式
        icon.addEventListener('contextmenu', (e) => {
            e.preventDefault();
            e.stopPropagation();
            showSettings();
        });

        // 支持双击打开设置(为Safari增加额外的交互方式)
        let lastClickTime = 0;
        icon.addEventListener('click', (e) => {
            const currentTime = new Date().getTime();
            if (currentTime - lastClickTime < 300) { // 双击间隔300ms
                e.preventDefault();
                e.stopPropagation();
                showSettings();
            }
            lastClickTime = currentTime;
        });

        // 添加拖动功能
        makeDraggable(icon);

        // 确保 body 存在后再添加图标
        if (document.body) {
            document.body.appendChild(icon);
        } else {
            document.addEventListener('DOMContentLoaded', () => {
                document.body.appendChild(icon);
            });
        }

        // 将图标引用存储到elements对象中
        elements.icon = icon;
    }

    // 显示设置界面
    function showSettings() {
        try {
            const settings = elements.settings || createSettingsUI();
            settings.style.display = 'block';
            showBackdrop();
            setTimeout(() => settings.style.opacity = '1', 10);
        } catch (error) {
            console.error('显示设置界面失败:', error);
            alert('无法显示设置界面,请检查控制台以获取详细信息');
        }
    }

    // 显示摘要
    async function showSummary() {
        const container = elements.container || createSummaryUI();
        const content = container.querySelector('#website-summary-content');
        
        // 如果容器有自定义位置,保持原位置;否则重置到屏幕中心
        const hasCustomPosition = container.hasAttribute('data-positioned');
        if (!hasCustomPosition) {
            container.style.left = '50%';
            container.style.top = '50%';
            container.style.transform = 'translate(-50%, -50%)';
        }
        
        // 显示容器和背景
        showBackdrop();
        container.style.display = 'block';
        setTimeout(() => container.style.opacity = '1', 10);
        
        // 显示加载中
        content.innerHTML = `<p style="text-align: center; color: ${config.theme === 'dark' ? '#bdc1c6' : '#666'};">正在获取总结...</p>`;
        
        try {
            // 获取页面内容
            const pageContent = getPageContent();
            if (!pageContent || pageContent.trim().length === 0) {
                throw new Error('无法获取页面内容');
            }
            
            console.log('页面内容长度:', pageContent.length);
            console.log('API配置:', {
                url: config.apiUrl,
                model: config.model,
                contentLength: pageContent.length
            });
            
            // 获取总结
            const summary = await getSummary(pageContent);
            if (!summary || summary.trim().length === 0) {
                throw new Error('API返回内容为空');
            }
            
            // 添加样式并渲染内容
            addMarkdownStyles();
            await renderContent(summary);
        } catch (error) {
            console.error('总结失败:', error);
            content.innerHTML = `
                <p style="text-align: center; color: #ff4444;">
                    获取总结失败:${error.message}<br>
                    <small style="color: ${config.theme === 'dark' ? '#bdc1c6' : '#666'};">
                        请检查控制台以获取详细错误信息
                    </small>
                </p>`;
        }
    }

    // 创建/显示背景
    function showBackdrop() {
        if (!elements.backdrop) {
            const backdrop = document.createElement('div');
            backdrop.id = 'website-summary-backdrop';
            const isDark = config.theme === 'dark';
            backdrop.style.cssText = `
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background-color: ${isDark ? 'rgba(32, 33, 36, 0.75)' : 'rgba(250, 250, 252, 0.75)'};
                backdrop-filter: blur(5px);
                z-index: 999997;
                display: none;
                opacity: 0;
                transition: opacity 0.3s ease;
            `;
            
            backdrop.addEventListener('click', (e) => {
                if (e.target === backdrop) {
                    hideUI();
                }
            });
            
            document.body.appendChild(backdrop);
            elements.backdrop = backdrop;
        } else {
            // 更新背景颜色以匹配当前主题
            const isDark = config.theme === 'dark';
            elements.backdrop.style.backgroundColor = isDark ? 'rgba(32, 33, 36, 0.75)' : 'rgba(250, 250, 252, 0.75)';
        }
        
        elements.backdrop.style.display = 'block';
        setTimeout(() => elements.backdrop.style.opacity = '1', 10);
    }

    // 隐藏UI
    function hideUI() {
        // 隐藏背景
        if (elements.backdrop) {
            elements.backdrop.style.opacity = '0';
            setTimeout(() => elements.backdrop.style.display = 'none', 300);
        }
        
        // 隐藏摘要容器
        if (elements.container) {
            elements.container.style.opacity = '0';
            setTimeout(() => elements.container.style.display = 'none', 300);
        }
    }

    // 创建摘要UI
    function createSummaryUI() {
        const container = document.createElement('div');
        container.id = 'website-summary-container';
        
        const isDark = config.theme === 'dark';
        let styles = `
            position: fixed;
            z-index: 999998;
            background: ${isDark ? darkColors.containerBg : 'rgba(255, 255, 255, 0.98)'};
            color: ${isDark ? darkColors.text : '#333'};
            border-radius: ${browserSupport.isMobile ? '8px' : '12px'};
            box-shadow: 0 8px 32px ${isDark ? 'rgba(0, 0, 0, 0.4)' : 'rgba(0, 0, 0, 0.08)'};
            padding: ${browserSupport.isMobile ? '12px' : '16px'};
            width: ${browserSupport.isMobile ? '92%' : '80%'};
            max-width: ${browserSupport.isMobile ? '100%' : '800px'};
            max-height: ${browserSupport.isMobile ? '85vh' : '80vh'};
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            display: none;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            overflow: hidden;
            opacity: 0;
            transition: opacity 0.3s ease;
            will-change: transform;
            -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
        `;

        // 添加backdrop-filter(如果支持)
        if (browserSupport.hasBackdropFilter) {
            styles += 'backdrop-filter: blur(10px);';
            styles += '-webkit-backdrop-filter: blur(10px);';
        }

        container.style.cssText = styles;

        // 标题栏
        const header = document.createElement('div');
        header.style.cssText = `
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 12px;
            cursor: move;
            padding-bottom: 8px;
            border-bottom: 1px solid ${isDark ? '#555' : '#eee'};
            user-select: none;
            -webkit-user-select: none;
        `;

        // 标题
        const title = document.createElement('h3');
        title.textContent = '网页总结';
        title.style.cssText = `
            margin: 0; 
            font-size: 18px; 
            color: ${isDark ? '#e8eaed' : '#333'};
            pointer-events: none;
        `;

        // 按钮容器
        const buttonContainer = document.createElement('div');
        buttonContainer.style.cssText = 'display: flex; gap: 8px; align-items: center;';

        // 复制按钮
        const copyBtn = document.createElement('button');
        copyBtn.textContent = '复制';
        copyBtn.style.cssText = `
            background: ${isDark ? '#8ab4f8' : '#4CAF50'};
            color: ${isDark ? '#202124' : 'white'};
            border: none;
            padding: 6px 12px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.2s;
        `;

        copyBtn.addEventListener('mouseover', () => {
            copyBtn.style.backgroundColor = isDark ? '#aecbfa' : '#45a049';
        });
        copyBtn.addEventListener('mouseout', () => {
            copyBtn.style.backgroundColor = isDark ? '#8ab4f8' : '#4CAF50';
        });

        copyBtn.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            const content = document.getElementById('website-summary-content').innerText;
            navigator.clipboard.writeText(content).then(() => {
                copyBtn.textContent = '已复制';
                setTimeout(() => copyBtn.textContent = '复制', 2000);
            });
        });

        // 关闭按钮
        const closeBtn = document.createElement('button');
        closeBtn.textContent = '×';
        closeBtn.style.cssText = `
            background: none;
            border: none;
            font-size: 24px;
            cursor: pointer;
            padding: 0 8px;
            color: ${isDark ? '#e8eaed' : '#666'};
            transition: color 0.2s;
        `;

        closeBtn.addEventListener('mouseover', () => closeBtn.style.color = '#ff4444');
        closeBtn.addEventListener('mouseout', () => closeBtn.style.color = isDark ? '#e8eaed' : '#666');
        closeBtn.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            hideUI();
        });

        // 内容区域
        const content = document.createElement('div');
        content.id = 'website-summary-content';
        content.style.cssText = `
            max-height: calc(80vh - 60px);
            overflow-y: auto;
            font-size: 14px;
            line-height: 1.6;
            padding: 8px 0;
            color: ${isDark ? '#e8eaed' : '#333'};
            -webkit-overflow-scrolling: touch;
            overscroll-behavior: contain;
        `;

        // 防止内容区域的滚动触发容器拖动
        content.addEventListener('mousedown', (e) => {
            e.stopPropagation();
        });
        content.addEventListener('touchstart', (e) => {
            e.stopPropagation();
        }, { passive: true });

        // 组装界面
        buttonContainer.appendChild(copyBtn);
        buttonContainer.appendChild(closeBtn);
        header.appendChild(title);
        header.appendChild(buttonContainer);
        container.appendChild(header);
        container.appendChild(content);
        document.body.appendChild(container);
        
        // 专门使用标题栏拖动
        makeDraggableByHeader(container, header);
        elements.container = container;
        return container;
    }

    // 专门用于通过标题栏拖动的函数
    function makeDraggableByHeader(element, handle) {
        let isDragging = false;
        let startX, startY, startLeft, startTop;
        
        // 鼠标/触摸开始事件
        function handleStart(e) {
            isDragging = true;
            
            // 记录初始位置
            const rect = element.getBoundingClientRect();
            
            // 如果使用了transform-translate,则切换到绝对定位
            if (element.style.transform && element.style.transform.includes('translate')) {
                element.style.transform = 'none';
                element.style.left = rect.left + 'px';
                element.style.top = rect.top + 'px';
                
                // 标记元素已被手动定位
                element.setAttribute('data-positioned', 'true');
            }
            
            startLeft = rect.left;
            startTop = rect.top;
            
            // 记录鼠标/触摸起始位置
            if (e.type === 'touchstart') {
                startX = e.touches[0].clientX;
                startY = e.touches[0].clientY;
                // 阻止默认行为只在触摸时需要
                e.preventDefault();
            } else {
                startX = e.clientX;
                startY = e.clientY;
                e.preventDefault();
            }
            
            // 移除过渡效果
            element.style.transition = 'none';
            
            // 添加移动和结束事件监听
            if (e.type === 'touchstart') {
                document.addEventListener('touchmove', handleMove, { passive: false });
                document.addEventListener('touchend', handleEnd);
                document.addEventListener('touchcancel', handleEnd);
            } else {
                document.addEventListener('mousemove', handleMove);
                document.addEventListener('mouseup', handleEnd);
            }
        }
        
        // 鼠标/触摸移动事件
        function handleMove(e) {
            if (!isDragging) return;
            
            let moveX, moveY;
            if (e.type === 'touchmove') {
                moveX = e.touches[0].clientX - startX;
                moveY = e.touches[0].clientY - startY;
                // 阻止默认滚动
                e.preventDefault();
            } else {
                moveX = e.clientX - startX;
                moveY = e.clientY - startY;
            }
            
            // 计算新位置
            const newLeft = startLeft + moveX;
            const newTop = startTop + moveY;
            
            // 边界检查
            const maxLeft = window.innerWidth - element.offsetWidth;
            const maxTop = window.innerHeight - element.offsetHeight;
            
            // 应用新位置
            element.style.left = Math.max(0, Math.min(newLeft, maxLeft)) + 'px';
            element.style.top = Math.max(0, Math.min(newTop, maxTop)) + 'px';
            
            // 标记元素已被手动定位
            element.setAttribute('data-positioned', 'true');
        }
        
        // 鼠标/触摸结束事件
        function handleEnd() {
            if (!isDragging) return;
            isDragging = false;
            
            // 移除事件监听
            document.removeEventListener('mousemove', handleMove);
            document.removeEventListener('mouseup', handleEnd);
            document.removeEventListener('touchmove', handleMove);
            document.removeEventListener('touchend', handleEnd);
            document.removeEventListener('touchcancel', handleEnd);
            
            // 恢复过渡效果
            element.style.transition = 'opacity 0.3s ease';
            
            // 保存位置状态
            saveWindowPosition(element);
        }
        
        // 保存窗口位置
        function saveWindowPosition(element) {
            if (element.id === 'website-summary-container') {
                const rect = element.getBoundingClientRect();
                // 只保存位置标记状态,不保存具体位置
                config.summaryWindowPositioned = true;
                scriptHandler.setValue('summaryWindowPositioned', true);
            }
        }
        
        // 仅在指定的标题栏上添加事件监听
        handle.addEventListener('mousedown', handleStart);
        handle.addEventListener('touchstart', handleStart, { passive: false });
        
        // 处理窗口变化
        window.addEventListener('resize', () => {
            if (element.hasAttribute('data-positioned')) {
                const rect = element.getBoundingClientRect();
                
                // 如果窗口超出视口边界,调整位置
                if (rect.right > window.innerWidth) {
                    element.style.left = Math.max(0, window.innerWidth - element.offsetWidth) + 'px';
                }
                
                if (rect.bottom > window.innerHeight) {
                    element.style.top = Math.max(0, window.innerHeight - element.offsetHeight) + 'px';
                }
            }
        });
        
        // 如果用户离开窗口,确保释放拖动状态
        window.addEventListener('blur', () => {
            if (isDragging) {
                handleEnd();
            }
        });
        
        // 检查是否应该恢复自定义位置
        if (element.id === 'website-summary-container' && config.summaryWindowPositioned) {
            // 标记元素有自定义位置
            element.setAttribute('data-positioned', 'true');
        }
    }

    // 创建设置界面
    function createSettingsUI() {
        const settingsContainer = document.createElement('div');
        settingsContainer.id = 'website-summary-settings';
        
        // 基础样式
        const isDark = config.theme === 'dark';
        settingsContainer.style.cssText = `
            position: fixed;
            z-index: 1000000;
            background: ${isDark ? 'rgba(32, 33, 36, 0.98)' : 'rgba(255, 255, 255, 0.98)'};
            color: ${isDark ? '#e8eaed' : '#333'};
            border-radius: 12px;
            box-shadow: 0 4px 20px ${isDark ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.15)'};
            padding: 20px;
            width: 400px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            display: none;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            will-change: transform;
            -webkit-backface-visibility: hidden;
            backface-visibility: hidden;
        `;

        if (browserSupport.hasBackdropFilter) {
            settingsContainer.style.backdropFilter = 'blur(10px)';
            settingsContainer.style.webkitBackdropFilter = 'blur(10px)';
        }

        // 标题栏
        const header = document.createElement('div');
        header.style.cssText = `
            display: flex; 
            justify-content: space-between; 
            align-items: center; 
            margin-bottom: 20px; 
            cursor: move;
            user-select: none;
            -webkit-user-select: none;
        `;

        const title = document.createElement('h3');
        title.textContent = '设置';
        title.style.cssText = `
            margin: 0; 
            color: ${isDark ? '#e8eaed' : '#333'};
            pointer-events: none;
        `;

        const closeBtn = document.createElement('button');
        closeBtn.textContent = '×';
        closeBtn.style.cssText = `
            background: none;
            border: none;
            font-size: 24px;
            cursor: pointer;
            padding: 0 8px;
            color: ${isDark ? '#e8eaed' : '#666'};
        `;
        closeBtn.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            settingsContainer.style.display = 'none';
            if (elements.backdrop) {
                elements.backdrop.style.opacity = '0';
                setTimeout(() => elements.backdrop.style.display = 'none', 300);
            }
        });

        // 表单
        const form = document.createElement('form');
        form.style.cssText = 'display: flex; flex-direction: column; gap: 16px;';
        
        // 创建输入字段函数
        function createField(id, label, value, type = 'text', placeholder = '') {
            const container = document.createElement('div');
            container.style.cssText = 'display: flex; flex-direction: column; gap: 4px;';
            
            const labelElem = document.createElement('label');
            labelElem.textContent = label;
            labelElem.style.cssText = `font-size: 14px; color: ${isDark ? '#e8eaed' : '#333'}; font-weight: 500;`;
            
            const input = document.createElement(type === 'textarea' ? 'textarea' : 'input');
            if (type !== 'textarea') input.type = type;
            input.id = id;
            input.value = value;
            input.placeholder = placeholder;
            input.autocomplete = 'off';
            input.setAttribute('data-form-type', 'other');
            
            const baseStyle = `
                width: 100%;
                padding: 8px;
                border: 1px solid ${isDark ? '#555' : '#ddd'};
                border-radius: 6px;
                font-family: inherit;
                background: ${isDark ? '#202124' : '#fff'};
                color: ${isDark ? '#e8eaed' : '#333'};
            `;
            input.style.cssText = type === 'textarea' ? baseStyle + 'height: 100px; resize: vertical;' : baseStyle;
            
            container.appendChild(labelElem);
            container.appendChild(input);
            return { container, input };
        }

        // 创建主题切换
        function createThemeSwitch() {
            const container = document.createElement('div');
            container.style.cssText = 'display: flex; align-items: center; gap: 12px; margin-bottom: 16px;';
            
            const label = document.createElement('label');
            label.textContent = '主题模式:';
            label.style.cssText = `font-size: 14px; color: ${isDark ? '#e8eaed' : '#333'}; font-weight: 500;`;
            
            const themeSwitch = document.createElement('div');
            themeSwitch.style.cssText = 'display: flex; gap: 8px;';
            
            const createThemeButton = (themeName, text) => {
                const btn = document.createElement('button');
                btn.textContent = text;
                btn.type = 'button';
                const isActive = config.theme === themeName;
                btn.style.cssText = `
                    padding: 6px 12px;
                    border-radius: 4px;
                    border: 1px solid ${isDark ? '#555' : '#ddd'};
                    background: ${isActive ? (isDark ? '#555' : '#007AFF') : 'transparent'};
                    color: ${isActive ? '#fff' : (isDark ? '#e8eaed' : '#333')};
                    cursor: pointer;
                    transition: all 0.2s;
                `;
                btn.addEventListener('click', async () => {
                    config.theme = themeName;
                    await scriptHandler.setValue('theme', themeName);
                    // 重新创建设置界面而不是移除
                    const oldSettings = elements.settings;
                    elements.settings = null;
                    showSettings();
                    if (oldSettings) {
                        oldSettings.remove();
                    }
                });
                return btn;
            };
            
            const lightBtn = createThemeButton('light', '浅色');
            const darkBtn = createThemeButton('dark', '深色');
            
            themeSwitch.appendChild(lightBtn);
            themeSwitch.appendChild(darkBtn);
            container.appendChild(label);
            container.appendChild(themeSwitch);
            
            return container;
        }
        
        // 创建字段
        const apiUrlField = createField('apiUrl', 'API URL', config.apiUrl, 'text', '输入API URL');
        const apiKeyField = createField('apiKey', 'API Key', config.apiKey, 'text', '输入API Key');
        const modelField = createField('model', 'AI 模型', config.model, 'text', '输入AI模型名称');
        const shortcutField = createField('shortcut', '快捷键', config.shortcut, 'text', '例如: option+a, ctrl+shift+s');
        const promptField = createField('prompt', '提示词', config.prompt, 'textarea', '输入提示词');
        
        // 添加主题切换
        form.appendChild(createThemeSwitch());
        
        // 添加字段到表单
        form.appendChild(apiUrlField.container);
        form.appendChild(apiKeyField.container);
        form.appendChild(modelField.container);
        form.appendChild(shortcutField.container);
        form.appendChild(promptField.container);
        
        // 保存按钮
        const saveBtn = document.createElement('button');
        saveBtn.textContent = '保存设置';
        saveBtn.type = 'button';
        saveBtn.style.cssText = `
            background: ${isDark ? '#8ab4f8' : '#007AFF'};
            color: ${isDark ? '#202124' : 'white'};
            border: none;
            padding: 10px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: 500;
            transition: background-color 0.2s;
        `;

        saveBtn.addEventListener('mouseover', () => {
            saveBtn.style.backgroundColor = isDark ? '#aecbfa' : '#0056b3';
        });
        saveBtn.addEventListener('mouseout', () => {
            saveBtn.style.backgroundColor = isDark ? '#8ab4f8' : '#007AFF';
        });
        
        // 保存逻辑
        saveBtn.addEventListener('click', async (e) => {
            e.preventDefault();
            
            // 获取并验证表单值
            const newApiUrl = apiUrlField.input.value.trim();
            const newApiKey = apiKeyField.input.value.trim();
            const newModel = modelField.input.value.trim();
            const newPrompt = promptField.input.value.trim();
            const newShortcut = shortcutField.input.value.trim();
            
            if (!newApiUrl || !newApiKey) {
                alert('请至少填写API URL和API Key');
                return;
            }

            try {
                // 使用scriptHandler保存设置
                await scriptHandler.setValue('apiUrl', newApiUrl);
                await scriptHandler.setValue('apiKey', newApiKey);
                await scriptHandler.setValue('model', newModel);
                await scriptHandler.setValue('prompt', newPrompt);
                await scriptHandler.setValue('shortcut', newShortcut);
                await scriptHandler.setValue('theme', config.theme);

                // 更新内存配置
                config.apiUrl = newApiUrl;
                config.apiKey = newApiKey;
                config.model = newModel;
                config.prompt = newPrompt;
                config.shortcut = newShortcut;
                
                // 更新快捷键
                keyManager.setup();

                // 显示成功提示
                showToast('设置已保存');
                
                // 关闭设置
                settingsContainer.style.display = 'none';
            } catch (error) {
                console.error('保存设置失败:', error);
                showToast('保存设置失败,请重试');
            }
        });

        // 组装界面
        header.appendChild(title);
        header.appendChild(closeBtn);
        form.appendChild(saveBtn);
        settingsContainer.appendChild(header);
        settingsContainer.appendChild(form);
        document.body.appendChild(settingsContainer);

        // 使用优化的拖拽功能,只允许通过标题栏拖动
        makeDraggableByHeader(settingsContainer, header);
        elements.settings = settingsContainer;
        return settingsContainer;
    }

    // 获取页面内容
    function getPageContent() {
        try {
            const clone = document.body.cloneNode(true);
            const elementsToRemove = clone.querySelectorAll('script, style, iframe, nav, header, footer, .ad, .advertisement, .social-share, .comment, .related-content');
            elementsToRemove.forEach(el => el.remove());
            return clone.innerText.replace(/\s+/g, ' ').trim().slice(0, 5000);
        } catch (error) {
            return document.body.innerText.slice(0, 5000);
        }
    }

    // 修改深色模式颜色方案
    const darkColors = {
        background: '#242526',           // 更柔和的深色背景
        containerBg: '#2d2d30',          // 容器背景色
        text: '#e4e6eb',                 // 更柔和的文字颜色
        secondaryText: '#b0b3b8',        // 次要文字颜色
        border: '#3e4042',               // 边框颜色
        codeBackground: '#3a3b3c',       // 代码块背景
        blockquoteBorder: '#4a4b4d',     // 引用块边框
        blockquoteText: '#cacbcc',       // 引用块文字
        linkColor: '#4e89e8'             // 链接颜色
    };

    // 修改 API 调用函数
    function getSummary(content) {
        return new Promise((resolve, reject) => {
            const apiKey = config.apiKey.trim();
            
            if (!apiKey) {
                reject(new Error('请先设置API Key'));
                return;
            }

            const requestData = {
                model: config.model,
                messages: [
                    {
                        role: 'system',
                        content: '你是一个专业的网页内容总结助手,善于使用markdown格式来组织信息。'
                    },
                    {
                        role: 'user',
                        content: config.prompt + '\n\n' + content
                    }
                ],
                temperature: 0.7,
                stream: false
            };

            // 处理 URL
            let apiUrl = config.apiUrl.trim();
            if (!apiUrl.startsWith('http://') && !apiUrl.startsWith('https://')) {
                apiUrl = 'https://' + apiUrl;
            }

            // 打印请求信息用于调试
            console.log('发送请求到:', apiUrl);
            console.log('请求数据:', JSON.stringify(requestData, null, 2));

            // 发送请求
            const xhr = typeof GM_xmlhttpRequest !== 'undefined' ? GM_xmlhttpRequest : (typeof GM !== 'undefined' && GM.xmlHttpRequest);
            
            if (!xhr) {
                reject(new Error('不支持的环境:无法发送跨域请求'));
                return;
            }

            xhr({
                method: 'POST',
                url: apiUrl,
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${apiKey}`,
                    'Accept': 'application/json'
                },
                data: JSON.stringify(requestData),
                timeout: 30000,
                onload: function(response) {
                    try {
                        console.log('收到响应:', response.status);
                        console.log('响应头:', response.responseHeaders);
                        console.log('响应内容:', response.responseText);

                        if (response.status === 429) {
                            reject(new Error('API请求过于频繁,请稍后再试'));
                            return;
                        }

                        if (response.status !== 200) {
                            reject(new Error(`API请求失败: HTTP ${response.status}`));
                            return;
                        }

                        let data;
                        try {
                            data = JSON.parse(response.responseText);
                        } catch (e) {
                            console.error('JSON解析失败:', e);
                            reject(new Error('API响应格式错误'));
                            return;
                        }

                        if (data.error) {
                            reject(new Error('API错误: ' + (data.error.message || JSON.stringify(data.error))));
                            return;
                        }

                        // 提取内容
                        let content = null;
                        
                        if (data.choices && Array.isArray(data.choices) && data.choices.length > 0) {
                            const choice = data.choices[0];
                            if (choice.message && choice.message.content) {
                                content = choice.message.content;
                            } else if (choice.text) {
                                content = choice.text;
                            }
                        }

                        if (!content && data.response) {
                            content = typeof data.response === 'string' ? data.response : JSON.stringify(data.response);
                        }

                        if (!content && data.content) {
                            content = data.content;
                        }

                        if (content) {
                            resolve(content.trim());
                        } else {
                            reject(new Error('无法从API响应中提取内容'));
                        }
                    } catch (error) {
                        console.error('处理响应时出错:', error);
                        reject(new Error('处理响应失败: ' + error.message));
                    }
                },
                onerror: function(error) {
                    console.error('请求错误:', error);
                    reject(new Error('请求失败: ' + (error.message || '网络错误')));
                },
                ontimeout: function() {
                    reject(new Error('请求超时'));
                }
            });
        });
    }

    // 配置 Marked 渲染器
    function configureMarked() {
        if (typeof marked === 'undefined') return;

        // 配置 marked 选项
        marked.setOptions({
            gfm: true,
            breaks: true,
            headerIds: true,
            mangle: false,
            smartLists: true,
            smartypants: true,
            highlight: function(code, lang) {
                return code;
            }
        });

        // 自定义渲染器
        const renderer = new marked.Renderer();

        // 自定义标题渲染 - 移除 ## 前缀
        renderer.heading = function(text, level) {
            return `<h${level}>${text}</h${level}>`;
        };

        // 自定义列表项渲染
        renderer.listitem = function(text) {
            return `<li><span class="bullet">•</span><span class="text">${text}</span></li>`;
        };

        // 自定义段落渲染
        renderer.paragraph = function(text) {
            return `<p>${text}</p>`;
        };

        // 自定义代码块渲染
        renderer.code = function(code, language) {
            return `<pre><code class="language-${language}">${code}</code></pre>`;
        };

        // 自定义引用块渲染
        renderer.blockquote = function(quote) {
            return `<blockquote>${quote}</blockquote>`;
        };

        // 设置渲染器
        marked.setOptions({ renderer });
    }

    // 修改 Markdown 样式
    function addMarkdownStyles() {
        const styleId = 'website-summary-markdown-styles';
        if (document.getElementById(styleId)) return;

        const isDark = config.theme === 'dark';
        const style = document.createElement('style');
        style.id = styleId;
        
        // 定义颜色变量
        const colors = {
            light: {
                text: '#2c3e50',
                background: '#ffffff',
                border: '#e2e8f0',
                link: '#2563eb',
                linkHover: '#1d4ed8',
                code: '#f8fafc',
                codeBorder: '#e2e8f0',
                blockquote: '#f8fafc',
                blockquoteBorder: '#3b82f6',
                heading: '#1e293b',
                hr: '#e2e8f0',
                marker: '#64748b'
            },
            dark: {
                text: '#e2e8f0',
                background: '#1e293b',
                border: '#334155',
                link: '#60a5fa',
                linkHover: '#93c5fd',
                code: '#1e293b',
                codeBorder: '#334155',
                blockquote: '#1e293b',
                blockquoteBorder: '#60a5fa',
                heading: '#f1f5f9',
                hr: '#334155',
                marker: '#94a3b8'
            }
        };

        const c = isDark ? colors.dark : colors.light;

        style.textContent = `
            #website-summary-content {
                font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", Arial, sans-serif;
                line-height: 1.7;
                color: ${c.text};
                font-size: 15px;
                padding: 20px;
                max-width: 800px;
                margin: 0 auto;
            }

            #website-summary-content h2 {
                font-family: -apple-system, BlinkMacSystemFont, "SF Pro Display", "Helvetica Neue", Arial, sans-serif;
                font-weight: 600;
                line-height: 1.3;
                margin: 1.8em 0 1em;
                color: ${c.heading};
                font-size: 1.6em;
                letter-spacing: -0.01em;
            }

            #website-summary-content h3 {
                font-size: 1.3em;
                margin: 1.5em 0 0.8em;
                color: ${c.heading};
                font-weight: 600;
                line-height: 1.4;
            }

            #website-summary-content p {
                margin: 0.8em 0;
                line-height: 1.75;
                letter-spacing: 0.01em;
            }

            #website-summary-content ul {
                margin: 0.6em 0;
                padding-left: 0.5em;
                list-style: none;
            }

            #website-summary-content ul li {
                display: flex;
                align-items: baseline;
                margin: 0.4em 0;
                line-height: 1.6;
                letter-spacing: 0.01em;
            }

            #website-summary-content ul li .bullet {
                color: ${c.marker};
                margin-right: 0.7em;
                font-weight: normal;
                flex-shrink: 0;
            }

            #website-summary-content ul li .text {
                flex: 1;
            }

            #website-summary-content blockquote {
                margin: 1.2em 0;
                padding: 0.8em 1.2em;
                background: ${c.blockquote};
                border-left: 4px solid ${c.blockquoteBorder};
                border-radius: 6px;
                color: ${isDark ? '#cbd5e1' : '#475569'};
                font-style: italic;
            }

            #website-summary-content blockquote p {
                margin: 0.4em 0;
            }

            #website-summary-content code {
                font-family: "SF Mono", Menlo, Monaco, Consolas, monospace;
                font-size: 0.9em;
                background: ${c.code};
                border: 1px solid ${c.codeBorder};
                border-radius: 4px;
                padding: 0.2em 0.4em;
            }

            #website-summary-content pre {
                background: ${c.code};
                border: 1px solid ${c.codeBorder};
                border-radius: 8px;
                padding: 1.2em;
                overflow-x: auto;
                margin: 1.2em 0;
            }

            #website-summary-content pre code {
                background: none;
                border: none;
                padding: 0;
                font-size: 0.9em;
                line-height: 1.6;
            }

            #website-summary-content strong {
                font-weight: 600;
                color: ${isDark ? '#f1f5f9' : '#1e293b'};
            }

            #website-summary-content em {
                font-style: italic;
                color: ${isDark ? '#cbd5e1' : '#475569'};
            }

            #website-summary-content hr {
                margin: 2em 0;
                border: none;
                border-top: 1px solid ${c.hr};
            }

            #website-summary-content table {
                width: 100%;
                border-collapse: collapse;
                margin: 1.2em 0;
                font-size: 0.95em;
            }

            #website-summary-content th,
            #website-summary-content td {
                padding: 0.8em;
                border: 1px solid ${c.border};
                text-align: left;
            }

            #website-summary-content th {
                background: ${c.code};
                font-weight: 600;
            }

            #website-summary-content img {
                max-width: 100%;
                height: auto;
                border-radius: 8px;
                margin: 1em 0;
            }

            @media (max-width: 768px) {
                #website-summary-content {
                    font-size: 14px;
                    padding: 16px;
                }

                #website-summary-content h2 {
                    font-size: 1.4em;
                }

                #website-summary-content h3 {
                    font-size: 1.2em;
                }
            }
        `;

        document.head.appendChild(style);
    }

    // 修改渲染内容函数
    async function renderContent(content) {
        const container = document.getElementById('website-summary-content');
        if (!container) return;
        
        try {
            if (!content || content.trim().length === 0) {
                throw new Error('内容为空');
            }

            // 确保 marked 已加载并配置
            if (typeof marked === 'undefined') {
                throw new Error('Markdown 渲染器未加载');
            }
            
            // 配置 marked
            configureMarked();

            // 渲染 Markdown
            const html = marked.parse(content);
            
            // 清空容器
            container.innerHTML = '';
            
            // 创建临时容器
            const temp = document.createElement('div');
            temp.innerHTML = html;
            
            // 逐段落输出,提升性能
            const fragments = Array.from(temp.children);
            const typeDelay = 20; // 每段延迟(毫秒)
            
            for (let fragment of fragments) {
                container.appendChild(fragment);
                await new Promise(resolve => setTimeout(resolve, typeDelay));
            }
        } catch (error) {
            console.error('渲染内容失败:', error);
            container.innerHTML = `
                <p style="text-align: center; color: #ff4444;">
                    渲染内容失败:${error.message}<br>
                    <small style="color: ${config.theme === 'dark' ? '#bdc1c6' : '#666'};">
                        请刷新页面重试
                    </small>
                </p>`;
        }
    }

    // 添加菜单命令
    function registerMenuCommands() {
        scriptHandler.registerMenuCommand('显示网页总结 (快捷键: ' + config.shortcut + ')', showSummary);
        scriptHandler.registerMenuCommand('打开设置', showSettings);
    }

    // 启动脚本
    waitForPageLoad();
})();