Greasy Fork

来自缓存

Greasy Fork is available in English.

聊天助手大纲

为多个AI聊天平台生成智能对话大纲,支持实时更新、层级结构、主题切换,提升聊天体验和内容导航效率

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         聊天助手大纲
// @namespace    http://tampermonkey.net/
// @version      0.0.2
// @description  为多个AI聊天平台生成智能对话大纲,支持实时更新、层级结构、主题切换,提升聊天体验和内容导航效率
// @author       xzhao
// @match        *://chatgpt.com/*
// @match        *://chat.deepseek.com/*
// @match        *://grok.com/*
// @match        *://www.qianwen.com/*
// @match        *://chat.qwen.ai/*
// @match        *://*.doubao.com/*
// @icon         https://cdn.deepseek.com/chat/icon.png
// @license      MIT
// @grant        none

// ==/UserScript==

(function() {
    // 全局配置
    const GLOBAL_CONFIG = {
        // 主题配置
        theme: {
            // 高亮配置
            highlightColor: '#83daff2a',
            highlightTime: 2000,
            
            // 当前主题模式
            currentTheme: 'light', // 'light' 或 'dark'
            
            // 颜色配置
            colors: {
                light: {
                    primary: '#28a745',
                    user: '#007acc',
                    background: '#ffffff',
                    border: '#ddd',
                    shadow: 'rgba(0,0,0,0.15)',
                    text: '#333',
                    headerBg: '#ffffff',
                    
                    // 标题级别颜色
                    headers: {
                        h1: '#dc3545',
                        h2: '#fd7e14', 
                        h3: '#ffc107',
                        h4: '#28a745',
                        h5: '#17a2b8',
                        h6: '#6f42c1'
                    }
                },
                dark: {
                    primary: '#4caf50',
                    user: '#64b5f6',
                    background: '#2d2d2d',
                    border: '#555',
                    shadow: 'rgba(0,0,0,0.3)',
                    text: '#e0e0e0',
                    headerBg: '#2d2d2d',
                    
                    // 标题级别颜色
                    headers: {
                        h1: '#f48fb1',
                        h2: '#ffab91', 
                        h3: '#fff176',
                        h4: '#81c784',
                        h5: '#4dd0e1',
                        h6: '#b39ddb'
                    }
                }
            },
            
            // 尺寸配置
            sizes: {
                outlineWidth: '300px',
                borderRadius: '8px',
                padding: '15px',
                fontSize: '14px',
                indentSize: 15
            }
        },
        
        // 功能配置
        features: {
            autoExpand: true,
            showUserMessages: true,
            showAIMessages: true,
            enableAnimation: true,
            isVisible: true, // 大纲是否可见
            textLength: 50,  //大纲展示的字符数
            debouncedInterval: 500  //大纲更新间隔
        },
        text:{
            title:"对话大纲"
        }
    };
    function judgePlatform(){
        // 根据当前URL判断平台
        if(window.location.hostname.includes('deepseek.com')){
            return 'deepseek';
        }
        if(window.location.hostname.includes('doubao.com')){
            return 'doubao';
        }
        if(window.location.hostname.includes('chatgpt.com')){
            return 'chatgpt';
        }
        if(window.location.hostname.includes('grok.com')){
            return 'grok';
        }
        if(window.location.hostname.includes('qianwen.com')){
            return 'tongyi';
        }
        if(window.location.hostname.includes('qwen.ai')){
            return 'qwen';
        }
        return 'unknown';
    }
    
    //获取解析所需配置
    function getParserConfig(platform){
        switch(platform){
            case 'deepseek':
                return {
                    //获取对话区域元素,返回一个不会被清除的节点作为监视根节点
                    selectChatArea:function(){
                        return document.querySelectorAll('.ds-scroll-area')[2];
                    },
                    //根据传入的监视根节点获取其对应的对话历史列表
                    getMessageList:function(root){ 
                        if(!root.firstChild||root.firstChild.tagName=="TEXTAREA"){
                            return null;
                        }
                        return root.firstChild.children;
                    }
                    ,
                    //判断是否为用户消息,传入参数为每一个消息对话框
                    determineMessageOwner:function(messageEle){
                        if(messageEle.dataset.umId!=undefined){
                            return MessageOwner.User;
                        }
                        return MessageOwner.Assistant;
                    }
                    ,
                    //将整个大纲元素插入到指定位置中,不要做其它处理,保证出错时会直接抛出异常
                    insertOutline:function(outlineEle){
                        let b1=document.querySelectorAll('.ds-scroll-area')[0].parentElement.parentElement.parentElement;
                        b1.appendChild(outlineEle);
                    }
                };
            case "doubao":
                return {
                    //获取对话区域元素,返回一个不会被清除的节点作为监视根节点
                    selectChatArea:function(){
                        return document.querySelector('[data-testid="scroll_view"]').parentElement.parentElement;
                    },
                    //根据传入的监视根节点获取其对应的对话历史列表
                    getMessageList:function(root){ 
                        if(!root || !root.querySelector){
                            return null;
                        }
                        const children = root.querySelectorAll('.container-PvPoAn');
                        if(!children){
                            return null;
                        }
                        return children;
                    }
                    ,
                    //判断是否为用户消息,传入参数为每一个消息对话框
                    determineMessageOwner:function(messageEle){
                        // 豆包中用户消息通常包含 send_message 的 data-testid
                        if(messageEle.querySelector('[data-testid*="send_message"]') || 
                           messageEle.querySelector('[data-testid="send_message"]')){
                            return MessageOwner.User;
                        }
                        // AI消息通常包含 receive_message 的 data-testid
                        if(messageEle.querySelector('[data-testid*="receive_message"]') || 
                           messageEle.querySelector('[data-testid="receive_message"]')){
                            return MessageOwner.Assistant;
                        }
                        return MessageOwner.Other;
                    }
                    ,
                    //将整个大纲元素插入到指定位置中
                    insertOutline:function(outlineEle){
                        // 找到豆包的主布局容器,插入到侧边栏区域
                        const chatLayout = document.querySelector('[data-testid="scroll_view"]')
                                .parentElement.parentElement.parentElement.parentElement.parentElement;
                        chatLayout.appendChild(outlineEle);
                    }
                };
            case "chatgpt":
                return {
                    //获取对话区域元素,返回一个不会被清除的节点作为监视根节点
                    selectChatArea:function(){
                        return document.querySelector('#main') || document.querySelector('main');
                    },
                    //根据传入的监视根节点获取其对应的对话历史列表
                    getMessageList:function(root){ 
                        if(!root || !root.querySelectorAll){
                            return null;
                        }
                        const messages = root.querySelectorAll('[data-message-author-role]');
                        if(messages){
                            return messages;
                        }
                        // 备选方案:查找包含对话的 article 元素
                        const articles = root.querySelectorAll('article');
                        if(articles && articles.length > 0){
                            return articles;
                        }
                        return null;
                    }
                    ,
                    //判断是否为用户消息,传入参数为每一个消息对话框
                    determineMessageOwner:function(messageEle){
                        // ChatGPT 使用 data-message-author-role 属性来标识消息类型
                        const authorRole = messageEle.getAttribute('data-message-author-role');
                        if(authorRole === 'user'){
                            return MessageOwner.User;
                        }
                        if(authorRole === 'assistant'){
                            return MessageOwner.Assistant;
                        }
                        
                        // 备选方案:通过查找子元素来判断
                        if(messageEle.querySelector('[data-message-author-role="user"]')){
                            return MessageOwner.User;
                        }
                        if(messageEle.querySelector('[data-message-author-role="assistant"]')){
                            return MessageOwner.Assistant;
                        }
                        
                        return MessageOwner.Other;
                    }
                    ,
                    //将整个大纲元素插入到指定位置中
                    insertOutline:function(outlineEle){
                        const mainContainer = document.querySelector('#main').parentElement.parentElement;
                        mainContainer.appendChild(outlineEle);
                    }
                };
            case "grok":
                return {
                    //获取对话区域元素,返回一个不会被清除的节点作为监视根节点
                    selectChatArea:function(){
                        return document.querySelector('#last-reply-container').parentElement;
                    },
                    //根据传入的监视根节点获取其对应的对话历史列表
                    getMessageList:function(root){ 
                        if(!root || !root.querySelectorAll){
                            return null;
                        }
                        let messages = root.querySelectorAll(':scope > .relative');
                        return [...messages,...root.querySelectorAll(':scope > #last-reply-container > div > .relative')];
                    }
                    ,
                    //判断是否为用户消息,传入参数为每一个消息对话框
                    determineMessageOwner:function(messageEle){
                        //根据对话框下面的按钮数量判断消息发送者
                        const l=messageEle.children[2].firstChild.children.length;
                        if(l<5){
                            return MessageOwner.User;
                        }
                        return MessageOwner.Assistant;
                    }
                    ,
                    //将整个大纲元素插入到指定位置中
                    insertOutline:function(outlineEle){
                        // 找到 Grok 的主容器
                        const chatContainer = document.querySelector('main');
                        chatContainer.parentElement.appendChild(outlineEle);
                    }
                };
            case "tongyi":
                return {
                    //获取对话区域元素,返回一个不会被清除的节点作为监视根节点
                    selectChatArea:function(){
                        return document.querySelector('.scrollWrapper-LOelOS');
                    },
                    //根据传入的监视根节点获取其对应的对话历史列表
                    getMessageList:function(root){ 
                        if(!root || !root.querySelectorAll){
                            return null;
                        }
                        // 尝试查找包含对话的元素
                        let messages = root.querySelectorAll('div[class^="content-"]');
                        return messages;
                    }
                    ,
                    //判断是否为用户消息,传入参数为每一个消息对话框
                    determineMessageOwner:function(messageEle){
                        let className=messageEle.parentElement.className;
                        // 通过类名判断
                        if(className.includes('questionItem')){
                            return MessageOwner.User;
                        }
                        className=messageEle.parentElement.parentElement.className;
                        if(className.includes('answerItem')){
                            return MessageOwner.Assistant;
                        }
                        
                        return MessageOwner.Other;
                    }
                    ,
                    //将整个大纲元素插入到指定位置中
                    insertOutline:function(outlineEle){
                        // 找到通义千问的主容器
                        const tongyiContainer = document.querySelectorAll('.mainContent-GBAlug')[1]
                                .parentElement.parentElement;
                        tongyiContainer.appendChild(outlineEle);
                    }
                };
            case "qwen":
                return {
                    //获取对话区域元素,返回一个不会被清除的节点作为监视根节点
                    selectChatArea:function(){
                        return document.querySelector('#chat-message-container')
                    },
                    //根据传入的监视根节点获取其对应的对话历史列表
                    getMessageList:function(root){ 
                        if(!root || !root.querySelectorAll){
                            return null;
                        }
                        let messages = root.querySelectorAll('.response-message-content, .chat-user-message');
                        return messages;
                    }
                    ,
                    //判断是否为用户消息,传入参数为每一个消息对话框
                    determineMessageOwner:function(messageEle){
                        if(messageEle.className.includes('chat-user-message')){
                            return MessageOwner.User;
                        }
                        
                        return MessageOwner.Assistant;
                    }
                    ,
                    //将整个大纲元素插入到指定位置中
                    insertOutline:function(outlineEle){
                        // 找到 Qwen 的主容器
                        const mainContainer = document.querySelector('.desktop-layout');
                        mainContainer.style.backgroundColor=getCurrentColors().background;
                        mainContainer.appendChild(outlineEle);
                    }
                };
            default: return null;
        }
    }
    const MessageOwner = Object.freeze({
        User:'user',
        Assistant:'assitant',
        Other:'other'
        });

    // 获取当前主题颜色
    function getCurrentColors() {
        return GLOBAL_CONFIG.theme.colors[GLOBAL_CONFIG.theme.currentTheme];
    }

    // 插入CSS样式
    function insertStyles() {
        const styleId = 'chat-outline-styles';
        if (document.getElementById(styleId)) return; // 避免重复插入
        
        const style = document.createElement('style');
        style.id = styleId;
        updateStyleContent(style);
        
        document.head.appendChild(style);
    }

    // 更新样式内容
    function updateStyleContent(style) {
        const colors = getCurrentColors();
        
        style.textContent = `
            /* 大纲容器样式 */
            #chat-outline {
                width: ${GLOBAL_CONFIG.theme.sizes.outlineWidth};
                background: ${colors.background};
                border-radius: ${GLOBAL_CONFIG.theme.sizes.borderRadius};
                padding: 0;
                box-shadow: 0 4px 12px ${colors.shadow};
                font-size: ${GLOBAL_CONFIG.theme.sizes.fontSize};
                transition: all 0.3s ease;
                display: ${GLOBAL_CONFIG.features.isVisible ? 'block' : 'none'};
                height: 100dvh;
            }
            
            /* 固定在右侧的大纲样式 */
            #chat-outline.outline-fixed-right {
                position: fixed;
                top: 0;
                right: 0;
                z-index: 10000;
                height: 100vh;
                border-radius: ${GLOBAL_CONFIG.theme.sizes.borderRadius} 0 0 ${GLOBAL_CONFIG.theme.sizes.borderRadius};
                border-right: none;
                box-shadow: -4px 0 12px ${colors.shadow};
            }
            
            /* 大纲头部样式 */
            .chat-outline-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                padding-left: 15px;
                border-bottom: 1px solid ${colors.border};
                background: ${colors.headerBg};
                border-radius: ${GLOBAL_CONFIG.theme.sizes.borderRadius} ${GLOBAL_CONFIG.theme.sizes.borderRadius} 0 0;
                height: 10%;
            }
            
            /* 大纲标题样式 */
            .chat-outline-title {
                margin: 0;
                color: ${colors.text};
                font-size: 16px;
                font-weight: bold;
            }
            
            /* 控制按钮容器 */
            .outline-controls {
                display: flex;
                gap: 8px;
            }
            
            /* 控制按钮样式 */
            .outline-btn {
                background: none;
                border: 1px solid ${colors.border};
                border-radius: 4px;
                padding: 4px 8px;
                cursor: pointer;
                font-size: 12px;
                color: ${colors.text};
                transition: all 0.2s ease;
            }
            
            .outline-btn:hover {
                background: ${colors.border};
                transform: scale(1.05);
            }
            
            #outline-content {
                overflow-y: auto;
                height: 90%;
            }
            
            /* 用户消息项样式 */
            .outline-user-item {
                margin: 8px 15px;
                padding: 8px;
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f0f8ff' : '#3a3a3a'};
                border-left: 3px solid ${colors.user};
                border-radius: 4px;
                cursor: pointer;
                transition: background-color 0.2s;
                color: ${colors.text};
            }
            
            .outline-user-item:hover {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#e6f3ff' : '#4a4a4a'};
            }
            
            /* AI消息容器样式 */
            .outline-ai-container {
                margin: 8px 15px;
                border-left: 3px solid ${colors.primary};
                border-radius: 4px;
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f8f8f8' : '#3a3a3a'};
            }
            
            /* AI消息头部样式 */
            .outline-ai-header {
                padding: 8px;
                cursor: pointer;
                font-weight: bold;
                display: flex;
                justify-content: space-between;
                align-items: center;
                transition: background-color 0.2s;
                color: ${colors.text};
            }
            
            .outline-ai-header:hover {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f0f0f0' : '#4a4a4a'};
            }
            
            /* AI消息简单项样式 */
            .outline-ai-item {
                margin: 8px 15px;
                padding: 8px;
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f8f8f8' : '#3a3a3a'};
                border-left: 3px solid ${colors.primary};
                border-radius: 4px;
                cursor: pointer;
                transition: background-color 0.2s;
                color: ${colors.text};
            }
            
            .outline-ai-item:hover {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f0f0f0' : '#4a4a4a'};
            }
            
            /* 树形节点样式 */
            .tree-node {
                margin: 4px 0;
                padding: 4px 8px;
                border-radius: 3px;
                cursor: pointer;
                display: flex;
                justify-content: space-between;
                align-items: center;
                transition: background-color 0.2s;
                color: ${colors.text};
            }
            
            .tree-node:hover {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#e9ecef' : '#4a4a4a'} !important;
            }
            
            .tree-node-level-0 {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#e9ecef' : '#404040'};
                font-size: 14px;
            }
            
            .tree-node-level-1 {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f1f3f4' : '#383838'};
                font-size: 13px;
            }
            
            .tree-node-level-2 {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f8f9fa' : '#353535'};
                font-size: 12px;
            }
            
            .tree-node-level-3 {
                background: ${GLOBAL_CONFIG.theme.currentTheme === 'light' ? '#f8f9fa' : '#353535'};
                font-size: 11px;
            }
            
            /* 切换按钮样式 */
            .toggle-btn {
                font-size: 14px;
                transition: transform 0.2s;
                cursor: pointer;
                margin-left: 8px;
                user-select: none;
                color: ${colors.text};
                padding: 4px;
                border-radius: 3px;
                display: inline-flex;
                align-items: center;
                justify-content: center;
                min-width: 20px;
                min-height: 20px;
                line-height: 1;
            }
            
            .toggle-btn:hover {
                background-color: ${colors.border};
                transform: scale(1.1);
            }
            
            .toggle-btn.collapsed {
                transform: rotate(-90deg);
            }
            
            .toggle-btn.collapsed:hover {
                background-color: ${colors.border};
                transform: rotate(-90deg) scale(1.1);
            }
            
            /* 标题级别边框颜色 */
            .header-level-1 { border-left: 2px solid ${colors.headers.h1}; }
            .header-level-2 { border-left: 2px solid ${colors.headers.h2}; }
            .header-level-3 { border-left: 2px solid ${colors.headers.h3}; }
            .header-level-4 { border-left: 2px solid ${colors.headers.h4}; }
            .header-level-5 { border-left: 2px solid ${colors.headers.h5}; }
            .header-level-6 { border-left: 2px solid ${colors.headers.h6}; }
            
            /* 动画效果 */
            .highlight-animation {
                animation: highlight 0.5s ease-in-out;
            }
            
            @keyframes highlight {
                0% { background-color: transparent; }
                50% { background-color: ${GLOBAL_CONFIG.theme.highlightColor}; }
                100% { background-color: transparent; }
            }
            
            /* 性能优化:使用 transform 和 opacity 进行动画 */
            .tree-node, .outline-user-item, .outline-ai-item, .outline-ai-header {
                will-change: transform;
                backface-visibility: hidden;
            }
            
            /* 显示按钮样式 */
            #show-outline-btn {
                position: fixed;
                top: 50%;
                right: 20px;
                transform: translateY(-50%);
                background: ${colors.background};
                border: 1px solid ${colors.border};
                border-radius: 50%;
                width: 40px;
                height: 40px;
                cursor: pointer;
                font-size: 16px;
                color: ${colors.text};
                box-shadow: 0 2px 8px ${colors.shadow};
                transition: all 0.3s ease;
                z-index: 9999;
                display: ${GLOBAL_CONFIG.features.isVisible ? 'none' : 'flex'};
                align-items: center;
                justify-content: center;
            }
            
            #show-outline-btn:hover {
                background: ${colors.border};
                transform: translateY(-50%) scale(1.1);
            }
        `;
    }


    // 构建标题层级树结构
    function buildHeaderTree(headers) {
        const tree = [];
        const stack = [];
        
        headers.forEach(header => {
            const level = parseInt(header.tagName.charAt(1)); // h1->1, h2->2, etc.
            const node = {
                element: header,
                level: level,
                text: header.textContent,
                children: []
            };
            
            // 找到合适的父节点
            while (stack.length > 0 && stack[stack.length - 1].level >= level) {
                stack.pop();
            }
            
            if (stack.length === 0) {
                tree.push(node);
            } else {
                stack[stack.length - 1].children.push(node);
            }
            
            stack.push(node);
        });
        
        return tree;
    }
    
    // 创建可展开收起的树形结构DOM元素
    function createTreeStructure(nodes, depth) {
        const container = document.createElement('div');
        container.style.marginLeft = `${depth * GLOBAL_CONFIG.theme.sizes.indentSize}px`;
        
        nodes.forEach(node => {
            const nodeWrapper = document.createElement('div');
            
            const nodeElement = document.createElement('div');
            nodeElement.className = `tree-node tree-node-level-${Math.min(depth, 3)} header-level-${node.level}`;
            
            const textSpan = document.createElement('span');
            textSpan.textContent = node.text;
            
            nodeElement.appendChild(textSpan);
            
            // 如果有子节点,添加展开/收起按钮
            if (node.children.length > 0) {
                const toggleBtn = document.createElement('span');
                toggleBtn.textContent = '▼';
                toggleBtn.className = 'toggle-btn';
                nodeElement.appendChild(toggleBtn);
                
                // 创建子节点容器
                const childContainer = createTreeStructure(node.children, depth + 1);
                childContainer.style.display = GLOBAL_CONFIG.features.autoExpand ? 'block' : 'none';
                
                // 添加展开/收起功能
                toggleBtn.onclick = (e) => {
                    e.stopPropagation();
                    const isExpanded = childContainer.style.display !== 'none';
                    childContainer.style.display = isExpanded ? 'none' : 'block';
                    toggleBtn.textContent = isExpanded ? '▶' : '▼';
                    toggleBtn.classList.toggle('collapsed', isExpanded);
                };
                
                nodeWrapper.appendChild(childContainer);
            }
            
            // 添加点击跳转功能(点击文本部分)
            nodeElement.onclick = (e) => {
                e.stopPropagation();
                node.element.scrollIntoView({ behavior: 'smooth', block: 'center' });
                highlightElement(node.element);
            };
            
            nodeWrapper.insertBefore(nodeElement, nodeWrapper.firstChild);
            container.appendChild(nodeWrapper);
        });
        
        return container;
    }
    
    // 高亮元素
    function highlightElement(element) {
        // 移除可能存在的高亮类
        element.classList.remove('highlight-animation');
        
        // 强制重排以确保类被移除
        element.offsetHeight;
        
        // 添加高亮类
        element.classList.add('highlight-animation');
        
        // 在动画结束后移除类
        setTimeout(() => {
            element.classList.remove('highlight-animation');
        }, GLOBAL_CONFIG.theme.highlightTime);
    }

    // 切换主题
    function toggleTheme() {
        GLOBAL_CONFIG.theme.currentTheme = GLOBAL_CONFIG.theme.currentTheme === 'light' ? 'dark' : 'light';
        
        // 更新样式
        const style = document.getElementById('chat-outline-styles');
        if (style) {
            updateStyleContent(style);
        }
        
        // 保存主题设置到localStorage
        localStorage.setItem('chat-outline-theme', GLOBAL_CONFIG.theme.currentTheme);
    }

    // 当大纲插入失败时,将其插入到body并固定在页面右侧
    function insertOutlineToBodyFixed(outlineEle) {
        // 添加固定定位的样式类
        outlineEle.classList.add('outline-fixed-right');
        
        // 插入到body
        document.body.appendChild(outlineEle);
        
        console.log('大纲已插入到body并固定在页面右侧');
    }

    // 切换大纲可见性
    function toggleOutlineVisibility() {
        GLOBAL_CONFIG.features.isVisible = !GLOBAL_CONFIG.features.isVisible;
        
        const outlineEle = document.getElementById('chat-outline');
        const showBtn = document.getElementById('show-outline-btn');
        
        if (outlineEle) {
            outlineEle.style.display = GLOBAL_CONFIG.features.isVisible ? 'block' : 'none';
        }
        
        if (showBtn) {
            showBtn.style.display = GLOBAL_CONFIG.features.isVisible ? 'none' : 'flex';
        }
        
        // 保存可见性设置到localStorage
        localStorage.setItem('chat-outline-visible', GLOBAL_CONFIG.features.isVisible);
    }

    // 创建显示按钮
    function createShowButton() {
        // 检查是否已存在显示按钮
        if (document.getElementById('show-outline-btn')) {
            return;
        }
        
        const showBtn = document.createElement('button');
        showBtn.id = 'show-outline-btn';
        showBtn.innerHTML = '📋';
        showBtn.title = '显示对话大纲';
        showBtn.onclick = toggleOutlineVisibility;
        
        document.body.appendChild(showBtn);
    }

    // 从localStorage加载设置
    function loadSettings() {
        const savedTheme = localStorage.getItem('chat-outline-theme');
        if (savedTheme && (savedTheme === 'light' || savedTheme === 'dark')) {
            GLOBAL_CONFIG.theme.currentTheme = savedTheme;
        }
        
        const savedVisible = localStorage.getItem('chat-outline-visible');
        if (savedVisible !== null) {
            GLOBAL_CONFIG.features.isVisible = savedVisible === 'true';
        }
    }

    function initOutlineEle(){
        const outlineEle = document.createElement('div');
        outlineEle.id = 'chat-outline';
        
        // 创建头部容器
        const header = document.createElement('div');
        header.className = 'chat-outline-header';
        
        // 添加标题
        const title = document.createElement('h3');
        title.textContent = GLOBAL_CONFIG.text.title;
        title.className = 'chat-outline-title';
        header.appendChild(title);
        
        // 创建控制按钮容器
        const controls = document.createElement('div');
        controls.className = 'outline-controls';
        
        // 刷新按钮
        const refreshBtn = document.createElement('button');
        refreshBtn.className = 'outline-btn';
        refreshBtn.innerHTML = '🔄';
        refreshBtn.title = '强制刷新大纲';
        refreshBtn.onclick = () => {
            // 触发强制刷新
            if (GLOBAL_OBJ.forceRefreshOutline) {
                GLOBAL_OBJ.forceRefreshOutline();
            }
        };
        
        // 展开/收起所有节点按钮
        const toggleAllBtn = document.createElement('button');
        toggleAllBtn.className = 'outline-btn';
        toggleAllBtn.innerHTML = '📂';
        toggleAllBtn.title = '展开/收起所有节点';
        toggleAllBtn.onclick = () => {
            if (GLOBAL_OBJ.toggleAllNodes) {
                GLOBAL_OBJ.toggleAllNodes();
                // 更新按钮图标
                toggleAllBtn.innerHTML = GLOBAL_OBJ.allExpanded ? '📂' : '📁';
                toggleAllBtn.title = GLOBAL_OBJ.allExpanded ? '收起所有节点' : '展开所有节点';
            }
        };
        
        // 主题切换按钮
        const themeBtn = document.createElement('button');
        themeBtn.className = 'outline-btn';
        themeBtn.innerHTML = GLOBAL_CONFIG.theme.currentTheme === 'light' ? '🌙' : '☀️';
        themeBtn.title = '切换主题';
        themeBtn.onclick = () => {
            toggleTheme();
            themeBtn.innerHTML = GLOBAL_CONFIG.theme.currentTheme === 'light' ? '🌙' : '☀️';
        };
        
        // 隐藏按钮
        const hideBtn = document.createElement('button');
        hideBtn.className = 'outline-btn';
        hideBtn.innerHTML = '✕';
        hideBtn.title = '隐藏大纲';
        hideBtn.onclick = toggleOutlineVisibility;
        
        controls.appendChild(refreshBtn);
        controls.appendChild(toggleAllBtn);
        controls.appendChild(themeBtn);
        controls.appendChild(hideBtn);
        header.appendChild(controls);
        
        outlineEle.appendChild(header);
        
        // 创建大纲内容容器
        const outlineContent = document.createElement('div');
        outlineContent.id = 'outline-content';
        outlineEle.appendChild(outlineContent);
        
        return outlineEle;
    }
    // 全局对象,用于存储需要全局访问的变量和函数
    const GLOBAL_OBJ = {
        // 缓存相关变量
        messageCache: new Map(),
        lastMessageCount: 0,
        MAX_CACHE_SIZE: 100, // 最大缓存条目数
        
        // 运行时对象
        currentObserver: null,
        currentChatArea: null,
        outlineContent: null,
        parserConfig: null,
        debouncedRefresh: null,
        getCachedChatArea: null,
        chatArea: null,
        // 展开/收起状态
        allExpanded: true, // 默认展开状态
        
        // 强制刷新函数
        forceRefreshOutline: null,
        toggleAllNodes: null
    };
    
    // 防抖函数
    function debounce(func, wait) {
        let timeout;
        return function executedFunction(...args) {
            const later = () => {
                clearTimeout(timeout);
                func(...args);
            };
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
        };
    }
    
    // 获取消息的唯一标识
    function getMessageId(index,messageElement) {
        let text=messageElement.textContent;
        // 获取消息唯一标识
        return index+text.substring(text.length-10, text.length);
    }
    
    // 检查消息是否已缓存且未变化
    function isMessageCached(messageElement, messageId) {
        if (!GLOBAL_OBJ.messageCache.has(messageId)) {
            return false;
        }
        
        const cached = GLOBAL_OBJ.messageCache.get(messageId);
        // 简单检查内容长度是否变化(适用于正在生成的消息)
        return cached.textLength === messageElement.textContent.length;
    }
    
    // 缓存消息信息
    function cacheMessage(messageElement, messageId, outlineElement) {
        // 如果缓存过大,清理最旧的条目
        if (GLOBAL_OBJ.messageCache.size >= GLOBAL_OBJ.MAX_CACHE_SIZE) {
            const firstKey = GLOBAL_OBJ.messageCache.keys().next().value;
            GLOBAL_OBJ.messageCache.delete(firstKey);
        }
        
        GLOBAL_OBJ.messageCache.set(messageId, {
            textLength: messageElement.textContent.length,
            outlineElement: outlineElement.cloneNode(true),
            originalElement: messageElement, // 保存原始消息元素的引用
            timestamp: Date.now()
        });
    }
    
    // 清理过期缓存
    function cleanupCache() {
        const now = Date.now();
        const maxAge = 5 * 60 * 1000; // 5分钟
        
        for (const [key, value] of GLOBAL_OBJ.messageCache.entries()) {
            if (now - value.timestamp > maxAge) {
                GLOBAL_OBJ.messageCache.delete(key);
            }
        }
    }
    
    // 强制清理所有缓存
    function clearAllCache() {
        GLOBAL_OBJ.messageCache.clear();
        GLOBAL_OBJ.lastMessageCount = 0;
        console.log('已清理所有缓存');
    }
    
    // 重新绑定事件监听器
    function rebindEventListeners(clonedElement, originalMessageElement) {
        // 绑定用户消息项的点击事件
        if (clonedElement.classList.contains('outline-user-item')) {
            clonedElement.onclick = () => {
                originalMessageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
                highlightElement(originalMessageElement);
            };
        }
        
        // 绑定AI消息项的点击事件
        if (clonedElement.classList.contains('outline-ai-item')) {
            clonedElement.onclick = () => {
                originalMessageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
                highlightElement(originalMessageElement);
            };
        }
        
        // 绑定AI消息容器的事件
        if (clonedElement.classList.contains('outline-ai-container')) {
            const aiHeader = clonedElement.querySelector('.outline-ai-header');
            if (aiHeader) {
                // 重新绑定头部点击事件
                const headerText = aiHeader.querySelector('span:first-child');
                if (headerText) {
                    aiHeader.onclick = (e) => {
                        e.stopPropagation();
                        originalMessageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
                        highlightElement(originalMessageElement);
                    };
                }
                
                // 重新绑定展开/收起按钮事件
                const toggleBtn = aiHeader.querySelector('.toggle-btn');
                if (toggleBtn) {
                    const treeContainer = aiHeader.nextElementSibling;
                    if (treeContainer) {
                        toggleBtn.onclick = (e) => {
                            e.stopPropagation();
                            const isExpanded = treeContainer.style.display !== 'none';
                            treeContainer.style.display = isExpanded ? 'none' : 'block';
                            toggleBtn.textContent = isExpanded ? '▶' : '▼';
                            toggleBtn.classList.toggle('collapsed', isExpanded);
                        };
                    }
                }
            }
        }
        
        // 重新绑定树形节点的事件
        const treeNodes = clonedElement.querySelectorAll('.tree-node');
        treeNodes.forEach(treeNode => {
            const toggleBtn = treeNode.querySelector('.toggle-btn');
            if (toggleBtn) {
                const nodeWrapper = treeNode.parentElement;
                const childContainer = nodeWrapper.querySelector('div:last-child');
                if (childContainer && childContainer !== treeNode) {
                    toggleBtn.onclick = (e) => {
                        e.stopPropagation();
                        const isExpanded = childContainer.style.display !== 'none';
                        childContainer.style.display = isExpanded ? 'none' : 'block';
                        toggleBtn.textContent = isExpanded ? '▶' : '▼';
                        toggleBtn.classList.toggle('collapsed', isExpanded);
                    };
                }
            }
            
            // 重新绑定树形节点的点击跳转事件
            // 需要从原始消息元素中找到对应的标题元素
            const nodeText = treeNode.querySelector('span:first-child');
            if (nodeText) {
                const headerText = nodeText.textContent;
                const headerElement = findHeaderByText(originalMessageElement, headerText);
                if (headerElement) {
                    treeNode.onclick = (e) => {
                        e.stopPropagation();
                        headerElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        highlightElement(headerElement);
                    };
                }
            }
        });
    }
    
    // 根据文本内容查找对应的标题元素
    function findHeaderByText(messageElement, headerText) {
        const headers = messageElement.querySelectorAll('h1, h2, h3, h4, h5, h6');
        for (const header of headers) {
            if (header.textContent === headerText) {
                return header;
            }
        }
        return null;
    }
    
    // 展开或收起所有节点
    function toggleAllNodes() {
        if (!GLOBAL_OBJ.outlineContent) {
            console.log('大纲内容容器不存在');
            return;
        }
        
        const newState = !GLOBAL_OBJ.allExpanded;
        GLOBAL_OBJ.allExpanded = newState;
        
        // 查找所有的切换按钮和对应的容器
        const toggleButtons = GLOBAL_OBJ.outlineContent.querySelectorAll('.toggle-btn');
        const treeContainers = GLOBAL_OBJ.outlineContent.querySelectorAll('.outline-ai-container > div:last-child');
        const childContainers = GLOBAL_OBJ.outlineContent.querySelectorAll('[style*="margin-left"]');
        
        // 处理AI消息容器的展开/收起
        toggleButtons.forEach(btn => {
            const container = btn.parentElement.nextElementSibling;
            if (container) {
                container.style.display = newState ? 'block' : 'none';
                btn.textContent = newState ? '▼' : '▶';
                btn.classList.toggle('collapsed', !newState);
            }
        });
        
        // 处理树形结构的展开/收起
        const treeNodes = GLOBAL_OBJ.outlineContent.querySelectorAll('.tree-node');
        treeNodes.forEach(node => {
            const toggleBtn = node.querySelector('.toggle-btn');
            if (toggleBtn) {
                const nodeWrapper = node.parentElement;
                const childContainer = nodeWrapper.querySelector('div:last-child');
                if (childContainer && childContainer !== node) {
                    childContainer.style.display = newState ? 'block' : 'none';
                    toggleBtn.textContent = newState ? '▼' : '▶';
                    toggleBtn.classList.toggle('collapsed', !newState);
                }
            }
        });
        
        console.log(`已${newState ? '展开' : '收起'}所有节点`);
    }
    
    function refreshOutlineItems(outlineBone, determineMessageOwnerFunc) {
        const chatArea= GLOBAL_OBJ.getCachedChatArea();
        if(!chatArea){
            console.log('无法定位到对话区域')
            return;
        }
        const cd = GLOBAL_OBJ.parserConfig.getMessageList(chatArea);
        if(cd==null){
            console.log("对话区域无效,大纲生成失败,chatArea:",chatArea)
            return;
        }
        console.log('刷新大纲,chatArea:',chatArea.firstChild)
        const currentMessageCount = cd.length;
        
        // 如果消息数量没有变化,检查是否需要更新
        if (currentMessageCount === GLOBAL_OBJ.lastMessageCount && currentMessageCount > 0) {
            // 检查最后一条消息是否还在变化(可能是AI正在回复)
            const lastMessage = cd[cd.length - 1];
            const lastMessageId = getMessageId(cd.length-1,lastMessage);
            
            if (isMessageCached(lastMessage, lastMessageId)) {
                return; // 没有变化,跳过更新
            }
        }
        
        // 使用文档片段来减少DOM操作
        const fragment = document.createDocumentFragment();
        let messageIndex = 0;
        let hasChanges = false;
        
        // 遍历对话生成大纲
        for (let i = 0; i < cd.length; i++) {
            const c = cd[i];
            const messageId = getMessageId(i,c);
            const messageType = determineMessageOwnerFunc(c);
            
            // 检查是否可以使用缓存
            if (isMessageCached(c, messageId)) {
                const cached = GLOBAL_OBJ.messageCache.get(messageId);
                const clonedElement = cached.outlineElement.cloneNode(true);
                
                // 重新绑定事件监听器
                rebindEventListeners(clonedElement, c);
                
                fragment.appendChild(clonedElement);
                if (messageType === MessageOwner.User || messageType === MessageOwner.Assistant) {
                    messageIndex++;
                }
                continue;
            }
            
            hasChanges = true;
            let outlineElement = null;
            
            switch (messageType) {
                case MessageOwner.User:
                    if (!GLOBAL_CONFIG.features.showUserMessages) break;
                    
                    messageIndex++;
                    outlineElement = createUserOutlineItem(c, messageIndex);
                    break;
                    
                case MessageOwner.Assistant:
                    if (!GLOBAL_CONFIG.features.showAIMessages) break;
                    
                    messageIndex++;
                    outlineElement = createAIOutlineItem(c, messageIndex);
                    break;
            }
            
            if (outlineElement) {
                fragment.appendChild(outlineElement);
                // 缓存新创建的元素
                cacheMessage(c, messageId, outlineElement);
            }
        }
        
        // 只有在有变化时才更新DOM
        if (hasChanges || currentMessageCount !== GLOBAL_OBJ.lastMessageCount) {
            // 清空并重新填充
            if ('replaceChildren' in outlineBone) {
                outlineBone.replaceChildren();
            } else {
                outlineBone.innerHTML = '';
            }
            outlineBone.appendChild(fragment);
        }
        
        GLOBAL_OBJ.lastMessageCount = currentMessageCount;
    }
    
    // 创建用户消息大纲项
    function createUserOutlineItem(messageElement, messageIndex) {
        const userItem = document.createElement('div');
        userItem.className = 'outline-user-item';
        
        const userText = messageElement.textContent.substring(0, GLOBAL_CONFIG.features.textLength) + 
                        (messageElement.textContent.length > GLOBAL_CONFIG.features.textLength ? '...' : '');
        userItem.textContent = `👤 ${messageIndex}. ${userText}`;
        
        // 添加点击跳转功能
        userItem.onclick = () => {
            messageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
            highlightElement(messageElement);
        };
        
        return userItem;
    }
    
    // 创建AI消息大纲项
    function createAIOutlineItem(messageElement, messageIndex) {
        // 检查是否有标题标签
        const headers = messageElement.querySelectorAll('h1, h2, h3, h4, h5, h6');
        
        if (headers.length > 0) {
            return createAIContainerWithHeaders(messageElement, messageIndex, headers);
        } else {
            return createSimpleAIItem(messageElement, messageIndex);
        }
    }
    
    // 创建带标题的AI消息容器
    function createAIContainerWithHeaders(messageElement, messageIndex, headers) {
        const aiContainer = document.createElement('div');
        aiContainer.className = 'outline-ai-container';
        
        // 创建AI消息头部
        const aiHeader = document.createElement('div');
        aiHeader.className = 'outline-ai-header';
        
        const headerText = document.createElement('span');
        const aiText = messageElement.textContent.substring(0, GLOBAL_CONFIG.features.textLength) + 
                     (messageElement.textContent.length > GLOBAL_CONFIG.features.textLength ? '...' : '');
        headerText.textContent = `🤖 ${messageIndex}. ${aiText}`;
        
        const toggleBtn = document.createElement('span');
        toggleBtn.textContent = '▼';
        toggleBtn.className = 'toggle-btn';
        
        aiHeader.appendChild(headerText);
        aiHeader.appendChild(toggleBtn);
        
        // 构建标题层级树
        const headerTree = buildHeaderTree(headers);
        const treeContainer = createTreeStructure(headerTree, 0);
        treeContainer.style.display = GLOBAL_CONFIG.features.autoExpand ? 'block' : 'none';
        
        // 添加展开/收起功能
        toggleBtn.onclick = (e) => {
            e.stopPropagation();
            const isExpanded = treeContainer.style.display !== 'none';
            treeContainer.style.display = isExpanded ? 'none' : 'block';
            toggleBtn.textContent = isExpanded ? '▶' : '▼';
            toggleBtn.classList.toggle('collapsed', isExpanded);
        };
        
        // 添加点击跳转功能
        aiHeader.onclick = (e) => {
            e.stopPropagation();
            messageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
            highlightElement(messageElement);
        };
        
        aiContainer.appendChild(aiHeader);
        aiContainer.appendChild(treeContainer);
        
        return aiContainer;
    }
    
    // 创建简单的AI消息项
    function createSimpleAIItem(messageElement, messageIndex) {
        const aiItem = document.createElement('div');
        aiItem.className = 'outline-ai-item';
        
        const aiText = messageElement.textContent.substring(0, GLOBAL_CONFIG.features.textLength) + 
                      (messageElement.textContent.length > GLOBAL_CONFIG.features.textLength ? '...' : '');
        aiItem.textContent = `🤖 ${messageIndex}. ${aiText}`;
        
        // 添加点击跳转功能
        aiItem.onclick = () => {
            messageElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
            highlightElement(messageElement);
        };
        
        return aiItem;
    }

    async function getEleWithRetry(getFunc, args=[], judgeRes=true, maxRetries = 10, retryDelay = 1000) {
        for(let attempt = 0; attempt < maxRetries; attempt++) {
            try {
                const res = getFunc(...args);
                if(!judgeRes)   return true;
                if(res) {
                    console.log(`成功获取到 chatArea,尝试次数: ${attempt + 1}`);
                    return res;
                }
                
                if(attempt < maxRetries - 1) {
                    console.log(`第 ${attempt + 1} 次获取 chatArea 失败,${retryDelay}ms 后重试...`);
                    await new Promise(resolve => setTimeout(resolve, retryDelay));
                }
            } catch(error) {
                console.error(`获取 chatArea 时发生错误 (尝试 ${attempt + 1}):`, error);
                if(attempt < maxRetries - 1) {
                    await new Promise(resolve => setTimeout(resolve, retryDelay));
                }
            }
        }
        
        console.error(`经过 ${maxRetries} 次尝试后仍无法获取到 chatArea`);
        return null;
    }

    // 设置 MutationObserver 监听
    function setupMutationObserver(chatArea) {
        // 如果已有观察者,先断开连接
        if (GLOBAL_OBJ.currentObserver) {
            GLOBAL_OBJ.currentObserver.disconnect();
            console.log('已断开原有的 MutationObserver');
        }
        
        // 创建新的观察者
        const observer = new MutationObserver((mutations) => {
            // 检查是否有实际的内容变化
            let hasContentChange = false;
            
            for (const mutation of mutations) {
                if (mutation.type === 'childList') {
                    // 检查是否有新增或删除的消息节点
                    if (mutation.addedNodes.length > 0 || mutation.removedNodes.length > 0) {
                        hasContentChange = true;
                        break;
                    }
                } else if (mutation.type === 'characterData') {
                    hasContentChange = true;
                    break;
                }
            }
            
            if (hasContentChange && GLOBAL_OBJ.debouncedRefresh) {
                GLOBAL_OBJ.debouncedRefresh();
            }
        });
        
        // 开始观察
        observer.observe(chatArea, {
            childList: true,
            subtree: true, // 监听子树变化以捕获消息内容更新
            attributes: false,
            characterData: true // 监听文本内容变化
        });
        
        // 保存观察者引用
        GLOBAL_OBJ.currentObserver = observer;
        GLOBAL_OBJ.currentChatArea = chatArea;
        
        console.log('已设置新的 MutationObserver 监听:', chatArea);
        return observer;
    }

    async function init() {
        // 加载保存的设置
        loadSettings();
        
        // 插入CSS样式
        insertStyles();
        
        // 创建显示按钮
        createShowButton();
        
        let platform = judgePlatform();
        if(platform === 'unknown') {
            console.log('不支持的平台');
            return;
        }
        
        const parserConfig = getParserConfig(platform);
        if(!parserConfig) {
            console.log('无法获取解析配置');
            return;
        }
        
        const outlineEle = initOutlineEle();

        try{
            // 插入大纲到页面
            const r=await getEleWithRetry(parserConfig.insertOutline, [outlineEle],false,5,1000);
            if(!r)  throw new EvalError("多次尝试插入大纲失败")
        }
        catch(e){
            console.error("大纲插入内容失败,将插入到body并固定在右侧:",e)
            // 当插入失败时,直接插入到body并固定在页面右侧
            insertOutlineToBodyFixed(outlineEle);
        }

        // 使用重试机制获取 chatArea
        console.log('开始获取 chatArea...');
        const chatArea = await getEleWithRetry(parserConfig.selectChatArea);
        
        if(!chatArea) {
            console.error('经过多次重试后仍未找到聊天区域,脚本初始化失败');
            return;
        }
        
        console.log('成功定位到 chatArea:', chatArea);
        GLOBAL_OBJ.chatArea=chatArea;
        
        // 获取大纲内容容器
        const outlineContent = outlineEle.querySelector('#outline-content');
        
        // 保存到全局对象
        GLOBAL_OBJ.outlineContent = outlineContent;
        GLOBAL_OBJ.parserConfig = parserConfig;
        
        // 创建防抖的刷新函数
        const debouncedRefresh = debounce(() => {
            refreshOutlineItems(GLOBAL_OBJ.outlineContent, GLOBAL_OBJ.parserConfig.determineMessageOwner);
        }, GLOBAL_CONFIG.features.debouncedInterval); // 300ms 防抖延迟
        
        GLOBAL_OBJ.debouncedRefresh = debouncedRefresh;

        GLOBAL_OBJ.getCachedChatArea=function(force_refresh=false){
            // 缓存选择器结果
            if (force_refresh||!this._cachedChatArea) {
                this._cachedChatArea = parserConfig.selectChatArea() || null;
                console.log('get chatArea:',this._cachedChatArea)
            }
            return this._cachedChatArea;
        }
        
        // 创建强制刷新函数
        const forceRefresh = () => {
            console.log('执行强制刷新...');
            
            // 清理所有缓存
            clearAllCache();
            
            // 强制重新获取chatArea
            const newChatArea = GLOBAL_OBJ.getCachedChatArea(true);
            if (newChatArea) {
                // 重新设置 MutationObserver 监听新的 chatArea
                setupMutationObserver(newChatArea);
                
                // 立即刷新大纲内容
                refreshOutlineItems(GLOBAL_OBJ.outlineContent, GLOBAL_OBJ.parserConfig.determineMessageOwner);
                console.log('强制刷新完成,已重新监听新的 chatArea');
            } else {
                console.error('强制刷新失败:无法获取到chatArea');
            }
        };
        
        // 将强制刷新函数设置为全局可访问
        GLOBAL_OBJ.forceRefreshOutline = forceRefresh;
        
        // 将展开/收起函数设置为全局可访问
        GLOBAL_OBJ.toggleAllNodes = toggleAllNodes;
        
        // 初始化大纲内容
        refreshOutlineItems(outlineContent, parserConfig.determineMessageOwner);
        
        // 设置 MutationObserver 监听聊天区域变化
        setupMutationObserver(chatArea);
        
        // 定期清理缓存
        setInterval(cleanupCache, 2 * 60 * 1000); // 每2分钟清理一次
        
        console.log('对话大纲生成脚本已启动');
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();