网页划词高亮工具

提供网页划词高亮功能

// ==UserScript==
// @name         网页划词高亮工具
// @namespace    http://tampermonkey.net/
// @version      0.1.1
// @description  提供网页划词高亮功能
// @author       sunny43
// @license      MIT
// @match        *://*/*
// @grant        GM_addStyle
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_registerMenuCommand
// ==/UserScript==

(function () {
    'use strict';

    const STYLE_PREFIX = 'sunny43-';

    // 全局变量
    let highlights = [];
    let currentPageUrl = window.location.href;
    let currentDomain = window.location.hostname;
    let settings = GM_getValue('highlight_settings', {
        colors: ['#ff909c', '#b89fff', '#74b4ff', '#70d382', '#ffcb7e'],
        activeColor: '#ff909c',
        minTextLength: 1,
        enableFuzzyMatch: true,
        maxContextDistance: 50,
        sidebarDescription: '高亮工具',
        sidebarWidth: 320,
        showFloatingButton: true
    });
    let savedRange = null; // 保存选区范围
    let ignoreNextClick = false; // 忽略下一次点击的标志
    let menuDisplayTimer = null; // 菜单显示定时器
    let menuOperationInProgress = false; // 添加菜单操作锁定
    // 禁用列表
    let disabledList = GM_getValue('disabled_list', {
        domains: [],
        urls: []
    });
    // 检查当前页面是否禁用高亮功能
    let isHighlightDisabled = disabledList.domains.includes(currentDomain) ||
        disabledList.urls.includes(currentPageUrl);
    let updateSidebarHighlights = null;

    GM_addStyle(`
        /* 高亮菜单样式 */
        .${STYLE_PREFIX}highlight-menu {
            position: absolute;
            background: #333336;
            border: none;
            border-radius: 24px;
            box-shadow: 0 4px 16px rgba(0,0,0,0.3);
            padding: 10px 8px;
            z-index: 9999;
            display: flex;
            flex-direction: row;
            align-items: center;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            color: #fff;
            opacity: 0; /* 初始隐藏 */
            transition: opacity 0.2s ease-in;
            pointer-events: none; /* 隐藏时不响应事件 */
        }
        .${STYLE_PREFIX}highlight-menu.${STYLE_PREFIX}show {
            opacity: 1;
            pointer-events: auto; /* 显示时响应事件 */
        }

        /* 菜单箭头样式 */
        .${STYLE_PREFIX}highlight-menu::after {
            content: '';
            position: absolute;
            bottom: -6px;
            left: var(--arrow-left, 50%);
            width: 12px;
            height: 6px;
            background-color: #333336;
            clip-path: polygon(0 0, 100% 0, 50% 100%);
            margin-left: -6px;
        }
        .${STYLE_PREFIX}highlight-menu.${STYLE_PREFIX}arrow-top::after {
            top: -6px;
            bottom: auto;
            clip-path: polygon(0 100%, 100% 100%, 50% 0);
        }

        /* 颜色选择区域 */
        .${STYLE_PREFIX}highlight-menu-colors {
            display: flex;
            flex-direction: row;
            align-items: center;
            margin: 0 2px;
            flex-wrap: nowrap;
            flex: 0 0 auto;
        }

        /* 颜色选择按钮 */
        .${STYLE_PREFIX}highlight-menu-color {
            width: 22px;
            height: 22px;
            border-radius: 50%;
            margin: 0 3px;
            cursor: pointer;
            position: relative;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: transform 0.15s ease;
            box-shadow: inset 0 0 0 1px rgba(255,255,255,0.12);
            flex-shrink: 0;
        }
        .${STYLE_PREFIX}highlight-menu-color:hover {
            transform: scale(1.12);
        }
        .${STYLE_PREFIX}highlight-menu-color.active::after {
            content: "";
            width: 12px;
            height: 12px;
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23333336' stroke-width='4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'%3E%3C/polyline%3E%3C/svg%3E");
            background-repeat: no-repeat;
            background-position: center;
            background-size: contain;
        }

        /* 菜单按钮通用样式 */
        .${STYLE_PREFIX}highlight-menu-action {
            height: 22px;
            margin: 0 2px;
            cursor: pointer;
            padding: 0 10px;
            border-radius: 12px;
            color: #fff;
            font-size: 13px;
            background: rgba(255,255,255,0.1);
            border: none;
            transition: all 0.15s ease;
            white-space: nowrap;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-shrink: 0;
        }
        .${STYLE_PREFIX}highlight-menu-action:hover {
            background: rgba(255,255,255,0.2);
        }

        /* 删除按钮样式 */
        .${STYLE_PREFIX}highlight-action-delete {
            color: #f0f0f0;
            font-weight: 500;
            position: relative;
            overflow: hidden;
            transition: all 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
            margin-left: 3px;
        }
        .${STYLE_PREFIX}highlight-action-delete:hover {
            background: rgba(255,82,82,0.12);
            color: #ff6b6b;
            transform: translateY(-1px);
            box-shadow: 0 2px 8px rgba(255,82,82,0.25);
        }
        .${STYLE_PREFIX}highlight-action-delete:active {
            transform: translateY(0px);
            background: rgba(255,82,82,0.2);
        }

        /* 闪烁效果用于高亮跳转 */
        @keyframes ${STYLE_PREFIX}highlightFlash {
            0%, 100% { opacity: 1; }
            50% { opacity: 0.3; }
        }
        .${STYLE_PREFIX}highlight-flash {
            animation: ${STYLE_PREFIX}highlightFlash 0.5s ease 4;
            box-shadow: 0 0 0 3px rgba(255, 255, 0, 0.7) !important;
            position: relative;
            z-index: 10;
        }

        /* 浮动按钮样式 */
        #${STYLE_PREFIX}floating-button {
            position: fixed;
            bottom: 20px;
            right: 20px;
            z-index: 10000;
            width: 33px;
            height: 33px;
            border: none;
            border-radius: 50%;
            cursor: pointer;
            background-color: #333336; /* 与菜单一致的背景 */
            color: #fff;
            font-size: 16px;
            box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
            transition: background-color 0.2s ease, transform 0.2s ease;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        #${STYLE_PREFIX}floating-button:hover {
            background-color: #4a4a4a;
            transform: scale(1.05);
        }
        #${STYLE_PREFIX}floating-button:active {
            transform: scale(0.95);
        }
        /* 侧边栏样式 */
        #${STYLE_PREFIX}sidebar {
            position: fixed;
            top: 0;
            right: -300px;
            width: 300px;
            height: 100%;
            background: linear-gradient(to bottom, #2c2c30, #1e1e22);
            box-shadow: -2px 0 8px rgba(0, 0, 0, 0.3);
            transition: right 0.3s ease;
            z-index: 9999;
        }
        /* 侧边栏打开时 */
        #${STYLE_PREFIX}sidebar.open {
            right: 0;
        }
    `);

    // 保存禁用列表
    function saveDisabledList() {
        GM_setValue('disabled_list', disabledList);
        // 刷新当前状态
        isHighlightDisabled = disabledList.domains.includes(currentDomain) ||
            disabledList.urls.includes(currentPageUrl);

        // 更新浮动按钮显示状态
        const floatingButton = document.getElementById(`${STYLE_PREFIX}floating-button`);
        if (floatingButton) {
            floatingButton.style.display = (settings.showFloatingButton && !isHighlightDisabled) ? 'flex' : 'none';
        }
    }

    // 禁用域名
    function disableDomain(domain) {
        if (!disabledList.domains.includes(domain)) {
            disabledList.domains.push(domain);
            saveDisabledList();
        }
    }

    // 启用域名
    function enableDomain(domain) {
        disabledList.domains = disabledList.domains.filter(d => d !== domain);
        saveDisabledList();
    }

    // 禁用URL
    function disableUrl(url) {
        if (!disabledList.urls.includes(url)) {
            disabledList.urls.push(url);
            saveDisabledList();
        }
    }

    // 启用URL
    function enableUrl(url) {
        disabledList.urls = disabledList.urls.filter(u => u !== url);
        saveDisabledList();
    }

    // 加载当前页面的高亮
    function loadHighlights() {
        const allHighlights = GM_getValue('highlights', {});
        highlights = allHighlights[currentPageUrl] || [];
        return highlights;
    }

    // 保存高亮到存储
    function saveHighlights() {
        const allHighlights = GM_getValue('highlights', {});
        allHighlights[currentPageUrl] = highlights;
        GM_setValue('highlights', allHighlights);
    }

    // 保存设置
    function saveSettings() {
        GM_setValue('highlight_settings', settings);
    }

    // 移除高亮菜单
    function removeHighlightMenu() {
        if (window.currentMenuCloseHandler) {
            document.removeEventListener('click', window.currentMenuCloseHandler);
            window.currentMenuCloseHandler = null;
        }
        const existingMenus = document.querySelectorAll(`.${STYLE_PREFIX}highlight-menu`);
        if (existingMenus.length) {
            existingMenus.forEach(menu => {
                menu.classList.remove(`${STYLE_PREFIX}show`);
                setTimeout(() => {
                    if (menu && menu.parentNode) {
                        menu.parentNode.removeChild(menu);
                    }
                }, 200);
            });
        }
        clearTimeout(menuDisplayTimer);
        ignoreNextClick = false;
        menuOperationInProgress = false;
    }

    // 高亮选中文本
    function highlightSelection(color) {
        if (isHighlightDisabled) {
            return null;
        }
        const selection = window.getSelection();
        if (!selection.rangeCount) return null;
        const range = selection.getRangeAt(0);
        const selectedText = selection.toString().trim();
        if (!selectedText || selectedText.length < settings.minTextLength) {
            return null;
        }
        const highlightId = 'highlight-' + Date.now() + '-' + Math.floor(Math.random() * 10000);
        const highlightElement = document.createElement('span');
        highlightElement.className = `${STYLE_PREFIX}highlight-marked`;
        highlightElement.dataset.highlightId = highlightId;
        highlightElement.style.backgroundColor = color;

        // ★ 先从未修改前的文本中提取上下文
        let prefix = '', suffix = '';
        if (range.startContainer.nodeType === Node.TEXT_NODE) {
            const originalText = range.startContainer.textContent;
            const startOffset = range.startOffset;
            const endOffset = startOffset + selectedText.length;
            prefix = extractValidContext(originalText, startOffset, 20, "backward");
            suffix = extractValidContext(originalText, endOffset, 20, "forward");
        }

        try {
            // 再进行DOM操作前,提取上下文后才调用 extractContents
            const fragment = range.extractContents();
            highlightElement.appendChild(fragment);
            range.insertNode(highlightElement);

            const highlight = {
                id: highlightId,
                text: selectedText,
                color: color,
                timestamp: Date.now(),
                url: currentPageUrl,
                prefix: prefix,    // 前置上下文
                suffix: suffix     // 后置上下文
            };

            highlights.push(highlight);
            saveHighlights();

            highlightElement.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                removeHighlightMenu();
                setTimeout(() => {
                    showHighlightEditMenu(e, highlightId);
                }, 10);
            });

            // 检查侧边栏是否打开,如果打开则刷新高亮列表
            const sidebar = document.getElementById(`${STYLE_PREFIX}sidebar`);
            if (sidebar && sidebar.style.right === '0px' && updateSidebarHighlights) {
                updateSidebarHighlights();
            }

            selection.removeAllRanges();
            return highlightId;
        } catch (e) {
            console.warn('高亮失败:', e);
            try {
                findAndHighlight(selectedText, color, highlightId);

                // 检查侧边栏是否打开,如果打开则刷新高亮列表
                const sidebar = document.getElementById(`${STYLE_PREFIX}sidebar`);
                if (sidebar && sidebar.style.right === '0px' && updateSidebarHighlights) {
                    updateSidebarHighlights();
                }

                return highlightId;
            } catch (error) {
                console.error('替代高亮方法也失败:', error);
                return null;
            }
        }
    }

    // 根据ID删除高亮
    function removeHighlightById(highlightId) {
        const highlightElement = document.querySelector(`.${STYLE_PREFIX}highlight-marked[data-highlight-id="${highlightId}"]`);
        if (highlightElement) {
            const textNode = document.createTextNode(highlightElement.textContent);
            highlightElement.parentNode.replaceChild(textNode, highlightElement);
        }
        highlights = highlights.filter(h => h.id !== highlightId);
        saveHighlights();

        // 检查侧边栏是否打开,如果打开则刷新高亮列表
        const sidebar = document.getElementById(`${STYLE_PREFIX}sidebar`);
        if (sidebar && sidebar.style.right === '0px' && updateSidebarHighlights) {
            updateSidebarHighlights();
        }
    }

    // 使用 MutationObserver 监听 DOM 变化,动态恢复高亮
    function observeDomChanges() {
        let debounceTimer;  // 新增变量用于防抖
        const observer = new MutationObserver((mutations) => {
            clearTimeout(debounceTimer);
            debounceTimer = setTimeout(() => {
                applyHighlights();
            }, 300);
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            characterData: true
        });
    }

    // 更改高亮颜色
    function changeHighlightColor(highlightId, newColor) {
        const highlightElement = document.querySelector(`.${STYLE_PREFIX}highlight-marked[data-highlight-id="${highlightId}"]`);
        if (highlightElement) {
            highlightElement.style.backgroundColor = newColor;
        }
        const index = highlights.findIndex(h => h.id === highlightId);
        if (index !== -1) {
            highlights[index].color = newColor;
            saveHighlights();
        }

        // 检查侧边栏是否打开,如果打开则刷新高亮列表
        const sidebar = document.getElementById(`${STYLE_PREFIX}sidebar`);
        if (sidebar && sidebar.style.right === '0px' && updateSidebarHighlights) {
            updateSidebarHighlights();
        }
    }

    // 显示/隐藏侧边栏
    function toggleSidebar(forceShow = true) {
        const sidebar = document.getElementById(`${STYLE_PREFIX}sidebar`);
        const floatingButton = document.getElementById(`${STYLE_PREFIX}floating-button`);
        if (!sidebar) return;

        if (forceShow) {
            sidebar.style.right = '0px';
            // 显示侧边栏时隐藏浮动按钮
            if (floatingButton) {
                floatingButton.style.display = 'none';
            }
            if (updateSidebarHighlights) {
                updateSidebarHighlights();
            }
        } else {
            const width = sidebar.style.width || '300px';
            const wasVisible = sidebar.style.right === '0px';
            sidebar.style.right = wasVisible ? `-${width}` : '0px';

            // 更新浮动按钮显示状态
            if (floatingButton) {
                if (wasVisible) {
                    // 关闭侧边栏时,根据设置和禁用状态决定是否显示浮动按钮
                    floatingButton.style.display = (settings.showFloatingButton && !isHighlightDisabled) ? 'flex' : 'none';
                } else {
                    // 打开侧边栏时,隐藏浮动按钮
                    floatingButton.style.display = 'none';
                }
            }

            if (sidebar.style.right === '0px' && updateSidebarHighlights) {
                updateSidebarHighlights();
            }
        }
    }

    // 切换浮动按钮显示/隐藏
    function toggleFloatingButton() {
        const floatingButton = document.getElementById(`${STYLE_PREFIX}floating-button`);
        if (!floatingButton) return;

        settings.showFloatingButton = !settings.showFloatingButton;
        // 即使设置为显示,在禁用页面也不显示按钮
        floatingButton.style.display = (settings.showFloatingButton && !isHighlightDisabled) ? 'flex' : 'none';
        saveSettings();
    }

    // 显示高亮编辑菜单
    function showHighlightEditMenu(event, highlightId) {
        if (isHighlightDisabled) {
            return;
        }
        removeHighlightMenu();
        if (menuOperationInProgress) return;
        menuOperationInProgress = true;
        event.preventDefault();
        event.stopPropagation();
        ignoreNextClick = true;
        const highlight = highlights.find(h => h.id === highlightId);
        if (!highlight) {
            menuOperationInProgress = false;
            return;
        }
        const menu = createHighlightMenu(false);
        menu.dataset.currentHighlightId = highlightId;
        menu.querySelectorAll(`.${STYLE_PREFIX}highlight-menu-color`).forEach(colorBtn => {
            colorBtn.classList.remove('active');
        });
        const activeColorButton = menu.querySelector(`.${STYLE_PREFIX}highlight-menu-color[data-color="${highlight.color}"]`);
        if (activeColorButton) {
            activeColorButton.classList.add('active');
        }
        const menuHeight = 50;
        let menuTop = event.clientY + window.scrollY - menuHeight - 10;
        let showAbove = true;
        if (event.clientY < menuHeight + 10) {
            menuTop = event.clientY + window.scrollY + 10;
            showAbove = false;
        }
        menu.style.top = `${menuTop}px`;
        const menuWidth = menu.offsetWidth || 200;
        let menuLeft;
        if (event.clientX - (menuWidth / 2) < 5) {
            menuLeft = 5;
        } else if (event.clientX + (menuWidth / 2) > window.innerWidth - 5) {
            menuLeft = window.innerWidth - menuWidth - 5;
        } else {
            menuLeft = event.clientX - (menuWidth / 2);
        }
        menu.style.left = `${menuLeft}px`;
        const arrowLeft = event.clientX - menuLeft;
        const minArrowLeft = 12;
        const maxArrowLeft = menuWidth - 12;
        const safeArrowLeft = Math.max(minArrowLeft, Math.min(arrowLeft, maxArrowLeft));
        menu.style.setProperty('--arrow-left', `${safeArrowLeft}px`);
        if (!showAbove) {
            menu.classList.add(`${STYLE_PREFIX}arrow-top`);
        } else {
            menu.classList.remove(`${STYLE_PREFIX}arrow-top`);
        }
        requestAnimationFrame(() => {
            menu.classList.add(`${STYLE_PREFIX}show`);
            // 使用 once:true 来自动清理事件监听
            document.addEventListener('click', function closeMenu(e) {
                if (ignoreNextClick) {
                    ignoreNextClick = false;
                    return;
                }
                if (!menu.contains(e.target)) {
                    removeHighlightMenu();
                }
            }, { once: true });
            setTimeout(() => {
                ignoreNextClick = false;
                menuOperationInProgress = false;
            }, 50);
        });
    }

    // 查找并高亮文本
    function findAndHighlight(searchText, color, highlightId) {
        // 遍历所有文本节点查找匹配内容
        const treeWalker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            null
        );
        while (treeWalker.nextNode()) {
            const node = treeWalker.currentNode;
            const textContent = node.textContent;
            if (!textContent || textContent.trim().length === 0) continue;
            const idx = textContent.indexOf(searchText);
            if (idx !== -1) {
                const range = document.createRange();
                range.setStart(node, idx);
                range.setEnd(node, idx + searchText.length);
                const highlightElement = document.createElement('span');
                highlightElement.className = `${STYLE_PREFIX}highlight-marked`;
                highlightElement.dataset.highlightId = highlightId;
                highlightElement.style.backgroundColor = color;
                try {
                    const fragment = range.extractContents();
                    highlightElement.appendChild(fragment);
                    range.insertNode(highlightElement);
                    highlightElement.addEventListener('click', (e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        showHighlightEditMenu(e, highlightId);
                    });
                    // 新高亮直接返回 true
                    return true;
                } catch (e) {
                    console.warn('应用高亮失败:', e);
                }
            }
        }
        return false;
    }

    // 应用页面上的所有高亮
    function applyHighlights() {
        // 按 timestamp 降序排序(从后向前恢复)
        highlights.sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));
        highlights.forEach(highlight => {
            const restored = advancedRestoreHighlight(highlight);
            if (!restored) {
                console.warn('多步恢复失败:', highlight.id);
            }
        });
    }

    // 创建高亮菜单
    function createHighlightMenu(isNewHighlight = true) {
        removeHighlightMenu();
        ignoreNextClick = true;
        const menu = document.createElement('div');
        menu.className = `${STYLE_PREFIX}highlight-menu`;
        menu.innerHTML = `
        <div class="${STYLE_PREFIX}highlight-menu-colors">
            ${settings.colors.map(color => `
                <div class="${STYLE_PREFIX}highlight-menu-color"
                    style="background-color: ${color};"
                    data-color="${color}">
                </div>
            `).join('')}
        </div>
    `;
        // 无论如何先置空操作ID
        menu.dataset.currentHighlightId = '';
        document.body.appendChild(menu);

        // 如果是新建高亮,确保所有颜色块没有激活状态
        if (isNewHighlight) {
            menu.querySelectorAll(`.${STYLE_PREFIX}highlight-menu-color`).forEach(el => {
                el.classList.remove('active');
            });
        }

        menu.querySelectorAll(`.${STYLE_PREFIX}highlight-menu-color`).forEach(el => {
            el.addEventListener('click', (e) => {
                const color = el.dataset.color;
                const isActive = el.classList.contains('active');
                const currentHighlightId = menu.dataset.currentHighlightId;
                if (isActive) {
                    if (currentHighlightId) {
                        removeHighlightById(currentHighlightId);
                        menu.dataset.currentHighlightId = '';
                        menu.querySelectorAll(`.${STYLE_PREFIX}highlight-menu-color`)
                            .forEach(colorEl => colorEl.classList.remove('active'));
                        const sel = window.getSelection();
                        sel.removeAllRanges();
                        if (savedRange) {
                            sel.addRange(savedRange.cloneRange());
                        }
                    } else {
                        window.getSelection().removeAllRanges();
                        menu.querySelectorAll(`.${STYLE_PREFIX}highlight-menu-color`)
                            .forEach(colorEl => colorEl.classList.remove('active'));
                    }
                    removeHighlightMenu();
                } else {
                    settings.activeColor = color;
                    saveSettings();
                    if (currentHighlightId) {
                        changeHighlightColor(currentHighlightId, color);
                    } else {
                        const selection = window.getSelection();
                        if (selection.toString().trim() === '' && savedRange) {
                            selection.removeAllRanges();
                            selection.addRange(savedRange.cloneRange());
                        }
                        const newHighlightId = highlightSelection(color);
                        if (newHighlightId) {
                            menu.dataset.currentHighlightId = newHighlightId;
                        }
                    }
                    menu.querySelectorAll(`.${STYLE_PREFIX}highlight-menu-color`)
                        .forEach(colorEl => colorEl.classList.toggle('active', colorEl.dataset.color === color));
                }
                e.stopPropagation();
            });
        });
        return menu;
    }

    // 显示高亮菜单
    function showHighlightMenu() {
        if (isHighlightDisabled) {
            return;
        }
        if (menuOperationInProgress) return;
        menuOperationInProgress = true;
        const selection = window.getSelection();
        const selectedText = selection.toString().trim();
        if (selectedText === '') {
            menuOperationInProgress = false;
            return;
        }
        const menu = createHighlightMenu(true);
        const range = selection.getRangeAt(0);
        const rects = range.getClientRects();
        if (rects.length === 0) {
            menuOperationInProgress = false;
            return;
        }
        const targetRect = rects[0];
        const menuHeight = 50;
        let initialTop = window.scrollY + targetRect.top - menuHeight - 8;
        let showAbove = true;
        if (targetRect.top < menuHeight + 10) {
            initialTop = window.scrollY + targetRect.bottom + 8;
            showAbove = false;
        }
        menu.style.top = `${initialTop}px`;
        setTimeout(() => {
            const menuWidth = menu.offsetWidth;
            const textCenterX = targetRect.left + (targetRect.width / 2);
            let menuLeft;
            if (textCenterX - (menuWidth / 2) < 5) {
                menuLeft = 5;
            } else if (textCenterX + (menuWidth / 2) > window.innerWidth - 5) {
                menuLeft = window.innerWidth - menuWidth - 5;
            } else {
                menuLeft = textCenterX - (menuWidth / 2);
            }
            menu.style.left = `${menuLeft}px`;
            menu.style.transform = 'none';
            const arrowLeft = textCenterX - menuLeft;
            const minArrowLeft = 12;
            const maxArrowLeft = menuWidth - 12;
            const safeArrowLeft = Math.max(minArrowLeft, Math.min(arrowLeft, maxArrowLeft));
            menu.style.setProperty('--arrow-left', `${safeArrowLeft}px`);
            if (!showAbove) {
                menu.classList.add(`${STYLE_PREFIX}arrow-top`);
            } else {
                menu.classList.remove(`${STYLE_PREFIX}arrow-top`);
            }
            requestAnimationFrame(() => {
                menu.classList.add(`${STYLE_PREFIX}show`);
            });
        }, 0);
        document.addEventListener('click', function closeMenu(e) {
            if (ignoreNextClick) {
                ignoreNextClick = false;
                return;
            }
            if (!menu.contains(e.target)) {
                removeHighlightMenu();
            }
        }, { once: true });
        setTimeout(() => {
            ignoreNextClick = false;
            menuOperationInProgress = false;
        }, 100);
    }

    // 注册事件
    function registerEvents() {
        document.addEventListener('mouseup', function (e) {
            if (isHighlightDisabled) {
                return;
            }
            if (e.target.closest(`.${STYLE_PREFIX}highlight-menu`)) {
                return;
            }
            const selection = window.getSelection();
            const selectedText = selection.toString().trim();
            if (selectedText.length < (settings.minTextLength || 1)) {
                return;
            }
            if (selection.rangeCount > 0) {
                savedRange = selection.getRangeAt(0).cloneRange();
            }
            removeHighlightMenu();
            clearTimeout(menuDisplayTimer);
            ignoreNextClick = true;
            menuDisplayTimer = setTimeout(() => {
                showHighlightMenu();
            }, 10);
        });
    }

    function fuzzyContextMatch(highlight) {
        // 如果未启用模糊匹配,则直接返回 false
        if (!settings.enableFuzzyMatch) return false;

        if (!highlight.text) return false;
        const textNodes = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            null
        );
        const pattern = highlight.text.trim();

        // 预处理前缀和后缀
        const storedPrefix = highlight.prefix ? highlight.prefix.trim() : '';
        const storedSuffix = highlight.suffix ? highlight.suffix.trim() : '';

        // 存储所有匹配项及其上下文评分
        const matches = [];

        // 记录匹配的总数,以便特殊处理单一匹配的情况
        let matchCount = 0;

        while (textNodes.nextNode()) {
            const node = textNodes.currentNode;
            const textContent = node.textContent;
            if (!textContent || textContent.trim().length === 0) continue;

            // 查找所有可能的匹配位置
            let startIdx = 0;
            while (startIdx < textContent.length) {
                const idx = textContent.indexOf(pattern, startIdx);
                if (idx === -1) break;

                matchCount++;

                // 获取上下文
                const actualPrefix = textContent.substring(Math.max(0, idx - 40), idx).trim();
                const actualSuffix = textContent.substring(idx + pattern.length,
                    idx + pattern.length + 40).trim();

                // 计算上下文匹配分数
                let score = 0;

                // 前缀匹配分数计算 (更宽松版)
                if (storedPrefix && actualPrefix) {
                    if (actualPrefix.includes(storedPrefix)) {
                        score += 10; // 前缀完全包含加10分
                    } else {
                        // 尝试寻找部分匹配
                        for (let i = 1; i <= Math.min(storedPrefix.length, 12); i++) {
                            const prefixEnd = storedPrefix.slice(-i);
                            if (actualPrefix.endsWith(prefixEnd)) {
                                score += i / 2; // 匹配前缀尾部,加分
                                break;
                            }
                        }

                        // 尝试在前缀中查找关键片段
                        if (storedPrefix.length > 6) {
                            for (let i = 0; i < storedPrefix.length - 5; i++) {
                                const fragment = storedPrefix.substring(i, i + 5);
                                if (actualPrefix.includes(fragment)) {
                                    score += 2.5; // 找到显著片段加2.5分
                                    break;
                                }
                            }
                        }
                    }
                }

                // 后缀匹配分数计算 (更宽松版)
                if (storedSuffix && actualSuffix) {
                    if (actualSuffix.includes(storedSuffix)) {
                        score += 10; // 后缀完全包含加10分
                    } else {
                        // 尝试寻找部分匹配
                        for (let i = 1; i <= Math.min(storedSuffix.length, 12); i++) {
                            const suffixStart = storedSuffix.slice(0, i);
                            if (actualSuffix.startsWith(suffixStart)) {
                                score += i / 2; // 匹配后缀头部,加分
                                break;
                            }
                        }

                        // 尝试在后缀中查找关键片段
                        if (storedSuffix.length > 6) {
                            for (let i = 0; i < storedSuffix.length - 5; i++) {
                                const fragment = storedSuffix.substring(i, i + 5);
                                if (actualSuffix.includes(fragment)) {
                                    score += 2.5; // 找到显著片段加2.5分
                                    break;
                                }
                            }
                        }
                    }
                }

                // 如果是单个字符的高亮,给予额外分数,避免完全相同的短文本被错过
                if (pattern.length <= 3 && (actualPrefix.includes(storedPrefix) || actualSuffix.includes(storedSuffix))) {
                    score += 5;
                }

                // 记录匹配项
                matches.push({
                    node,
                    idx,
                    score,
                    actualPrefix,
                    actualSuffix
                });

                startIdx = idx + 1; // 继续搜索下一个匹配
            }
        }

        // 特殊情况:如果页面上只有一个匹配,直接使用它
        if (matchCount === 1 && matches.length === 1) {
            const match = matches[0];
            try {
                const range = document.createRange();
                range.setStart(match.node, match.idx);
                range.setEnd(match.node, match.idx + pattern.length);

                const highlightElement = document.createElement('span');
                highlightElement.className = `${STYLE_PREFIX}highlight-marked`;
                highlightElement.dataset.highlightId = highlight.id;
                highlightElement.style.backgroundColor = highlight.color;

                const fragment = range.extractContents();
                highlightElement.appendChild(fragment);
                range.insertNode(highlightElement);

                highlightElement.addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    showHighlightEditMenu(e, highlight.id);
                });

                return true;
            } catch (e) {
                console.warn('唯一模糊匹配高亮失败:', e);
            }
        }

        // 如果有多个匹配项,选择分数最高的
        if (matches.length > 0) {
            // 按分数降序排序
            matches.sort((a, b) => b.score - a.score);
            const bestMatch = matches[0];

            // 降低得分阈值到2,使更多匹配可以被接受
            const threshold = matchCount > 1 ? 2 : 0.5;

            if (bestMatch.score >= threshold) {
                // 构造高亮
                try {
                    const range = document.createRange();
                    range.setStart(bestMatch.node, bestMatch.idx);
                    range.setEnd(bestMatch.node, bestMatch.idx + pattern.length);

                    const highlightElement = document.createElement('span');
                    highlightElement.className = `${STYLE_PREFIX}highlight-marked`;
                    highlightElement.dataset.highlightId = highlight.id;
                    highlightElement.style.backgroundColor = highlight.color;

                    const fragment = range.extractContents();
                    highlightElement.appendChild(fragment);
                    range.insertNode(highlightElement);

                    highlightElement.addEventListener('click', (e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        showHighlightEditMenu(e, highlight.id);
                    });

                    return true;
                } catch (e) {
                    console.warn('模糊匹配插入高亮失败:', e);
                }
            } else {
                console.log('模糊匹配分数过低,尝试进一步降低要求:', {
                    text: pattern,
                    bestScore: bestMatch.score
                });

                // 如果分数太低但至少有一个匹配,可以考虑用最后的回退机制
                if (matches.length > 0 && pattern.length <= 5) {
                    // 对于短文本,如果我们有任何匹配并且上下文也有一些匹配,就使用它
                    const bestMatch = matches[0];
                    try {
                        const range = document.createRange();
                        range.setStart(bestMatch.node, bestMatch.idx);
                        range.setEnd(bestMatch.node, bestMatch.idx + pattern.length);

                        const highlightElement = document.createElement('span');
                        highlightElement.className = `${STYLE_PREFIX}highlight-marked`;
                        highlightElement.dataset.highlightId = highlight.id;
                        highlightElement.style.backgroundColor = highlight.color;

                        console.log('使用回退机制恢复短文本高亮:', pattern);

                        const fragment = range.extractContents();
                        highlightElement.appendChild(fragment);
                        range.insertNode(highlightElement);

                        highlightElement.addEventListener('click', (e) => {
                            e.preventDefault();
                            e.stopPropagation();
                            showHighlightEditMenu(e, highlight.id);
                        });

                        return true;
                    } catch (e) {
                        console.warn('回退机制高亮失败:', e);
                    }
                }
            }
        }

        return false;
    }

    function advancedRestoreHighlight(highlight) {
        // 检查是否已经有相同ID的高亮存在
        const existingHighlight = document.querySelector(`.${STYLE_PREFIX}highlight-marked[data-highlight-id="${highlight.id}"]`);
        if (existingHighlight) {
            // 高亮已存在,不需要重复恢复
            return true;
        }

        // 使用文本上下文匹配恢复高亮
        const contextRestored = restoreHighlightUsingContext(highlight);
        if (contextRestored) {
            // 只保存最新一次恢复记录
            highlight.recoveryHistory = {
                timestamp: Date.now(),
                method: 'contextMatch',
                success: true
            };
            saveHighlights(); // 保存更新后的恢复历史
            return true;
        }

        // 尝试模糊匹配
        if (fuzzyContextMatch(highlight)) {
            highlight.recoveryHistory = {
                timestamp: Date.now(),
                method: 'fuzzyContext',
                success: true
            };
            saveHighlights();
            return true;
        }

        // 记录失败状态
        highlight.recoveryHistory = {
            timestamp: Date.now(),
            method: 'fallback',
            success: false
        };
        saveHighlights();
        return false;
    }

    function restoreHighlightUsingContext(highlight) {
        // 遍历页面中所有文本节点
        const treeWalker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            null
        );

        // 如果存在前缀和后缀信息,预处理它们以便于比较
        const storedPrefix = highlight.prefix ? highlight.prefix.trim() : '';
        const storedSuffix = highlight.suffix ? highlight.suffix.trim() : '';

        // 存储所有可能的匹配及其得分
        const matches = [];

        // 记录找到多少个完全相同的文本
        let exactTextMatches = 0;

        while (treeWalker.nextNode()) {
            const node = treeWalker.currentNode;
            const textContent = node.textContent;
            if (!textContent || textContent.trim().length === 0) continue;

            const idx = textContent.indexOf(highlight.text);
            if (idx !== -1) {
                // 记录找到了一个文本匹配
                exactTextMatches++;

                // 获取当前节点中匹配区域前后的上下文
                const actualPrefix = textContent.substring(Math.max(0, idx - 30), idx).trim();
                const actualSuffix = textContent.substring(idx + highlight.text.length,
                    idx + highlight.text.length + 30).trim();

                // 计算上下文匹配得分
                let score = 1; // 基础分:找到了文本

                // 前缀匹配得分计算 (改进版)
                if (storedPrefix && actualPrefix) {
                    if (actualPrefix.includes(storedPrefix)) {
                        score += 10; // 前缀完全包含加10分
                    } else if (storedPrefix.length > 3) {
                        // 尝试匹配前缀的尾部
                        for (let i = Math.min(storedPrefix.length, actualPrefix.length); i >= 3; i--) {
                            if (storedPrefix.slice(-i) === actualPrefix.slice(-i)) {
                                score += i / 2; // 匹配长度越长分数越高
                                break;
                            }
                        }

                        // 另外尝试寻找前缀中的部分匹配
                        if (storedPrefix.length >= 8) {
                            for (let i = 0; i < storedPrefix.length - 6; i++) {
                                const fragment = storedPrefix.substring(i, i + 6);
                                if (actualPrefix.includes(fragment)) {
                                    score += 3; // 找到部分匹配加3分
                                    break;
                                }
                            }
                        }
                    }
                }

                // 后缀匹配得分计算 (改进版)
                if (storedSuffix && actualSuffix) {
                    if (actualSuffix.includes(storedSuffix)) {
                        score += 10; // 后缀完全包含加10分
                    } else if (storedSuffix.length > 3) {
                        // 尝试匹配后缀的开头
                        for (let i = Math.min(storedSuffix.length, actualSuffix.length); i >= 3; i--) {
                            if (storedSuffix.slice(0, i) === actualSuffix.slice(0, i)) {
                                score += i / 2; // 匹配长度越长分数越高
                                break;
                            }
                        }

                        // 另外尝试寻找后缀中的部分匹配
                        if (storedSuffix.length >= 8) {
                            for (let i = 0; i < storedSuffix.length - 6; i++) {
                                const fragment = storedSuffix.substring(i, i + 6);
                                if (actualSuffix.includes(fragment)) {
                                    score += 3; // 找到部分匹配加3分
                                    break;
                                }
                            }
                        }
                    }
                }

                matches.push({
                    node,
                    idx,
                    score,
                    actualPrefix,
                    actualSuffix
                });
            }
        }

        // 特殊情况处理:如果页面上只有一个文本匹配,直接使用它
        if (exactTextMatches === 1 && matches.length === 1) {
            const match = matches[0];
            try {
                const range = document.createRange();
                range.setStart(match.node, match.idx);
                range.setEnd(match.node, match.idx + highlight.text.length);

                const highlightElement = document.createElement('span');
                highlightElement.className = `${STYLE_PREFIX}highlight-marked`;
                highlightElement.dataset.highlightId = highlight.id;
                highlightElement.style.backgroundColor = highlight.color;

                const fragment = range.extractContents();
                highlightElement.appendChild(fragment);
                range.insertNode(highlightElement);

                highlightElement.addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    showHighlightEditMenu(e, highlight.id);
                });

                return true;
            } catch (e) {
                console.warn('唯一文本匹配恢复高亮失败:', e);
            }
        }

        // 如果找到多个匹配项,选择得分最高的
        if (matches.length > 0) {
            // 按得分降序排序
            matches.sort((a, b) => b.score - a.score);
            const bestMatch = matches[0];

            // 降低匹配阈值,从5降到3,使得更多的匹配可以被接受
            const minScore = exactTextMatches > 1 ? 3 : 1;

            if (bestMatch.score >= minScore) {
                try {
                    const range = document.createRange();
                    range.setStart(bestMatch.node, bestMatch.idx);
                    range.setEnd(bestMatch.node, bestMatch.idx + highlight.text.length);

                    const highlightElement = document.createElement('span');
                    highlightElement.className = `${STYLE_PREFIX}highlight-marked`;
                    highlightElement.dataset.highlightId = highlight.id;
                    highlightElement.style.backgroundColor = highlight.color;

                    const fragment = range.extractContents();
                    highlightElement.appendChild(fragment);
                    range.insertNode(highlightElement);

                    highlightElement.addEventListener('click', (e) => {
                        e.preventDefault();
                        e.stopPropagation();
                        showHighlightEditMenu(e, highlight.id);
                    });

                    return true;
                } catch (e) {
                    console.warn('上下文匹配恢复高亮失败:', e);
                }
            } else {
                console.log('匹配分数过低,尝试模糊匹配:', {
                    text: highlight.text,
                    bestScore: bestMatch.score,
                    matchCount: matches.length
                });
            }
        }

        return false;
    }

    function extractValidContext(text, start, count, direction) {
        // direction: "backward" 从 start 往前提取, "forward" 从 start 往后提取
        let result = "";
        let processedChars = 0;

        // 对于短文本或单个字符,我们提取更多上下文
        const adjustedCount = count * (text.length <= 3 ? 2 : 1);

        if (direction === "backward") {
            for (let i = start - 1; i >= 0 && processedChars < adjustedCount * 2; i--) {
                const ch = text.charAt(i);
                // 只计算有效字符(中文、英文、数字)
                if (/[\u4e00-\u9fffA-Za-z0-9]/.test(ch)) {
                    result = ch + result;
                    processedChars++;
                    if (processedChars >= adjustedCount) break;
                } else {
                    // 空格和标点也记录,但不计入有效字符数
                    result = ch + result;
                }
            }
        } else { // forward
            for (let i = start; i < text.length && processedChars < adjustedCount * 2; i++) {
                const ch = text.charAt(i);
                // 只计算有效字符(中文、英文、数字)
                if (/[\u4e00-\u9fffA-Za-z0-9]/.test(ch)) {
                    result += ch;
                    processedChars++;
                    if (processedChars >= adjustedCount) break;
                } else {
                    // 空格和标点也记录,但不计入有效字符数
                    result += ch;
                }
            }
        }
        return result;
    }

    // 添加浮动按钮和侧边栏功能
    function createFloatingButtonAndSidebar() {
        // 创建浮动按钮
        const floatingButton = document.createElement('button');
        floatingButton.id = `${STYLE_PREFIX}floating-button`;
        // 使用 SVG 图标,代表"汉堡菜单"
        floatingButton.innerHTML = `
            <svg viewBox="0 0 100 80" width="16" height="16" fill="#ccc" xmlns="http://www.w3.org/2000/svg">
                <rect width="100" height="10"></rect>
                <rect y="30" width="100" height="10"></rect>
                <rect y="60" width="100" height="10"></rect>
            </svg>
        `;
        // 根据设置和禁用状态决定是否显示
        floatingButton.style.display = (settings.showFloatingButton && !isHighlightDisabled) ? 'flex' : 'none';
        document.body.appendChild(floatingButton);
        // 创建侧边栏(初始隐藏)
        const sidebar = document.createElement('div');
        sidebar.id = `${STYLE_PREFIX}sidebar`;
        Object.assign(sidebar.style, {
            position: 'fixed',
            top: '0',
            right: '-300px',
            width: '300px',
            height: '100%',
            boxShadow: '-2px 0 8px rgba(0, 0, 0, 0.3)',
            transition: 'none',
            zIndex: '9999',
            overflow: 'hidden', // 改为hidden,内部内容区域单独设置overflow
            display: 'flex',
            flexDirection: 'column',
            color: '#f0f0f0',
            fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
            background: 'linear-gradient(to bottom, #262630, #1a1a22)', // 更暗、更专业的渐变色
            boxShadow: '-4px 0 20px rgba(0, 0, 0, 0.25)', // 增强阴影深度感
            borderLeft: '1px solid rgba(255, 255, 255, 0.06)', // 添加微妙的边框
        });

        // 构建侧边栏内部结构
        sidebar.innerHTML = `
            <div class="${STYLE_PREFIX}sidebar-header">
                <div class="${STYLE_PREFIX}sidebar-title" title="双击修改标题">
                    ${settings.sidebarDescription || '网页划词高亮工具'}
                </div>
                <div class="${STYLE_PREFIX}sidebar-controls">
                    <button class="${STYLE_PREFIX}sidebar-close" title="关闭侧边栏">
                        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                            <path d="M18 6L6 18M6 6l12 12"></path>
                        </svg>
                    </button>
                </div>
            </div>

            <div class="${STYLE_PREFIX}sidebar-tabs">
                <button class="${STYLE_PREFIX}sidebar-tab active" data-tab="highlights">高亮列表</button>
                <button class="${STYLE_PREFIX}sidebar-tab" data-tab="disabled">禁用管理</button>
            </div>

            <div class="${STYLE_PREFIX}sidebar-content">
                <div class="${STYLE_PREFIX}tab-panel active" data-panel="highlights">
                    <div class="${STYLE_PREFIX}highlights-list"></div>
                </div>

                <div class="${STYLE_PREFIX}tab-panel" data-panel="disabled">
                    <div class="${STYLE_PREFIX}disabled-container"></div>
                </div>
            </div>
        `;

        document.body.appendChild(sidebar);
        setTimeout(() => {
            sidebar.style.transition = 'right 0.3s ease';
        }, 10);

        // 设置侧边栏内部元素样式
        const header = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-header`);
        Object.assign(header.style, {
            display: 'flex',
            justifyContent: 'space-between',
            alignItems: 'center',
            boxSizing: 'border-box',
            borderBottom: '1px solid rgba(255, 255, 255, 0.08)', // 更微妙的边框
            height: '42px', // 增加高度使其更易于点击
            background: 'rgba(0, 0, 0, 0.15)', // 轻微的背景色调
            padding: '0 16px', // 更合理的内边距
        });

        const title = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-title`);
        Object.assign(title.style, {
            fontSize: '13px',
            fontWeight: '600',
            flex: '1',
            overflow: 'hidden',
            textOverflow: 'ellipsis',
            whiteSpace: 'nowrap',
            cursor: 'default',
            letterSpacing: '0.3px', // 增加字母间距提高可读性
            opacity: '0.9',
        });

        const controls = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-controls`);
        Object.assign(controls.style, {
            display: 'flex',
            gap: '8px'
        });

        // 设置按钮样式
        sidebar.querySelectorAll(`.${STYLE_PREFIX}sidebar-controls button`).forEach(btn => {
            Object.assign(btn.style, {
                background: 'none',
                border: 'none',
                cursor: 'pointer',
                padding: '3px',         // 从5px减小到3px
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                color: '#ccc',
                borderRadius: '3px',
                transition: 'background-color 0.2s'
            });

            // 添加按钮悬停效果
            btn.addEventListener('mouseenter', () => {
                btn.style.backgroundColor = 'rgba(255, 255, 255, 0.1)';
            });

            btn.addEventListener('mouseleave', () => {
                btn.style.backgroundColor = 'transparent';
            });
        });

        // 设置标签页样式
        const tabs = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-tabs`);
        Object.assign(tabs.style, {
            display: 'flex',
            borderBottom: '1px solid rgba(255, 255, 255, 0.08)',
            padding: '0',
            justifyContent: 'center',
            backgroundColor: 'rgba(0, 0, 0, 0.12)',
            height: '38px'
        });

        sidebar.querySelectorAll(`.${STYLE_PREFIX}sidebar-tab`).forEach(tab => {
            Object.assign(tab.style, {
                height: '100%', // 占满容器高度
                cursor: 'pointer',
                fontWeight: '500', // 稍微加粗
                background: 'none',
                border: 'none',
                color: '#ccc',
                borderBottom: '2px solid transparent',
                margin: '0',
                transition: 'all 0.2s ease',
                flex: '1',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                letterSpacing: '0.3px', // 增加字母间距提高可读性
                fontSize: '12px', // 减小字体
                padding: '0 12px', // 添加水平内边距
                borderRadius: '0',  // 移除边角圆角
                opacity: '0.75', // 非激活状态降低不透明度
            });
        });

        // 激活的标签页样式
        const activeTab = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-tab.active`);
        if (activeTab) {
            Object.assign(activeTab.style, {
                color: '#fff',
                borderBottom: '2px solid rgba(190, 60, 60, 0.8)', // 改为指定颜色
                backgroundColor: 'rgba(255, 144, 156, 0.08)', // 使用主色的半透明版本
                opacity: '1',
            });
        }

        // 内容区域样式
        const contentArea = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-content`);
        Object.assign(contentArea.style, {
            flex: '1',
            overflow: 'hidden',
            position: 'relative'
        });

        // 设置面板样式
        sidebar.querySelectorAll(`.${STYLE_PREFIX}tab-panel`).forEach(panel => {
            Object.assign(panel.style, {
                height: '100%',
                width: '100%',
                position: 'absolute',
                top: '0',
                left: '0',
                padding: '14px 14px 14px 14px',  // 修改为:上右下左,底部padding设为0
                boxSizing: 'border-box',
                overflow: 'auto',
                display: 'none'
            });
        });

        // 显示当前活动面板
        const activePanel = sidebar.querySelector(`.${STYLE_PREFIX}tab-panel.active`);
        if (activePanel) {
            activePanel.style.display = 'block';
        }

        // 添加侧边栏拖拽调整区域(位于侧边栏的最左侧)
        const resizer = document.createElement('div');
        Object.assign(resizer.style, {
            position: 'absolute',
            left: '0',
            top: '0',
            width: '5px',
            height: '100%',
            cursor: 'ew-resize',
            backgroundColor: 'transparent'
        });
        sidebar.appendChild(resizer);

        // 拖拽事件逻辑
        resizer.addEventListener('mousedown', initResize);

        function initResize(e) {
            e.preventDefault();
            window.addEventListener('mousemove', resizeSidebar);
            window.addEventListener('mouseup', stopResize);
        }

        function resizeSidebar(e) {
            // 计算出新的宽度:侧边栏右对齐,宽度 = 窗口宽度 - 鼠标水平位置
            const newWidth = window.innerWidth - e.clientX;
            // 限制最小宽度为 150px,最大宽度为窗口 80%
            if (newWidth >= 150 && newWidth <= window.innerWidth * 0.8) {
                sidebar.style.width = newWidth + 'px';
                // 更新设置中的宽度
                settings.sidebarWidth = newWidth;
                saveSettings();
            }
        }

        function stopResize(e) {
            window.removeEventListener('mousemove', resizeSidebar);
            window.removeEventListener('mouseup', stopResize);
        }

        // 标签页切换事件
        sidebar.querySelectorAll(`.${STYLE_PREFIX}sidebar-tab`).forEach(tab => {
            tab.addEventListener('click', () => {
                // 移除所有标签页和面板的活动状态
                sidebar.querySelectorAll(`.${STYLE_PREFIX}sidebar-tab`).forEach(t => {
                    t.classList.remove('active');
                    t.style.color = '#ccc';
                    t.style.borderBottom = '2px solid transparent';
                    t.style.backgroundColor = 'transparent';
                });

                sidebar.querySelectorAll(`.${STYLE_PREFIX}tab-panel`).forEach(p => {
                    p.classList.remove('active');
                    p.style.display = 'none';
                });

                // 激活当前标签和面板
                tab.classList.add('active');
                tab.style.color = '#fff';
                tab.style.borderBottom = '2px solid rgba(190, 60, 60, 0.8)'; // 改为指定颜色

                const panelId = tab.getAttribute('data-tab');
                const panel = sidebar.querySelector(`.${STYLE_PREFIX}tab-panel[data-panel="${panelId}"]`);
                if (panel) {
                    panel.classList.add('active');
                    panel.style.display = 'block';
                }
            });

            // 添加悬停效果
            tab.addEventListener('mouseenter', () => {
                if (!tab.classList.contains('active')) {
                    tab.style.backgroundColor = 'rgba(255, 144, 156, 0.05)'; // 轻微的主色背景
                    tab.style.borderBottom = '2px solid'; // 淡化的主色边框
                }
            });

            tab.addEventListener('mouseleave', () => {
                if (!tab.classList.contains('active')) {
                    tab.style.backgroundColor = 'transparent';
                    tab.style.borderBottom = '2px solid transparent';
                }
            });
        });

        // 标题双击编辑功能
        const titleElement = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-title`);
        titleElement.addEventListener('dblclick', () => {
            const currentTitle = titleElement.textContent.trim() || '高亮工具';
            const input = document.createElement('input');
            input.type = 'text';
            input.value = currentTitle;

            // 美化输入框样式
            Object.assign(input.style, {
                width: '100%',
                fontSize: '14px',           // 从16px减小到14px
                fontWeight: '500',
                padding: '2px 6px',         // 调整内边距使其更美观
                boxSizing: 'border-box',
                border: '1px solid rgba(116, 180, 255, 0.5)',
                borderRadius: '3px',        // 添加圆角
                outline: 'none',
                background: 'rgba(0, 0, 0, 0.2)',
                color: '#fff',
                transition: 'all 0.15s ease', // 添加过渡效果
                boxShadow: '0 0 0 1px rgba(116, 180, 255, 0.3)'
            });

            // 替换标题内容为输入框
            titleElement.innerHTML = '';
            titleElement.appendChild(input);
            input.focus();
            input.select();

            // 添加输入框聚焦样式
            input.addEventListener('focus', () => {
                input.style.background = 'rgba(20, 20, 20, 0.4)';
                input.style.boxShadow = '0 0 0 2px rgba(116, 180, 255, 0.4)';
            });

            // 确认修改:输入框失焦或按下 Enter 键时更新标题
            const confirmChange = () => {
                const newTitle = input.value.trim() || '高亮工具';
                settings.sidebarDescription = newTitle;
                titleElement.textContent = newTitle;
                saveSettings();
            };

            input.addEventListener('blur', confirmChange);
            input.addEventListener('keydown', (event) => {
                if (event.key === 'Enter') {
                    input.blur();
                } else if (event.key === 'Escape') {
                    // 按ESC键取消编辑
                    titleElement.textContent = currentTitle;
                    input.blur();
                }
            });
        });

        // 关闭按钮事件
        const closeButton = sidebar.querySelector(`.${STYLE_PREFIX}sidebar-close`);
        closeButton.addEventListener('click', () => {
            sidebar.style.right = `-${parseInt(sidebar.style.width)}px`;

            // 侧边栏关闭时,如果设置允许显示浮动按钮且当前页面未禁用,则恢复显示浮动按钮
            if (settings.showFloatingButton && !isHighlightDisabled) {
                floatingButton.style.display = 'flex';
            }
        });

        // 浮动按钮点击后切换侧边栏的显示和隐藏
        floatingButton.addEventListener('click', () => {
            if (sidebar.style.right === '0px') {
                sidebar.style.right = `-${parseInt(sidebar.style.width)}px`;
                // 如果设置允许显示浮动按钮且当前页面未禁用,则显示浮动按钮
                if (settings.showFloatingButton && !isHighlightDisabled) {
                    floatingButton.style.display = 'flex';
                }
            } else {
                sidebar.style.right = '0px';
                // 当侧边栏显示时,隐藏浮动按钮
                floatingButton.style.display = 'none';
                // 刷新高亮列表
                if (updateSidebarHighlights) {
                    updateSidebarHighlights();
                }
            }
        });

        // 初始设置宽度
        if (settings.sidebarWidth) {
            sidebar.style.width = `${settings.sidebarWidth}px`;
            sidebar.style.right = `-${settings.sidebarWidth}px`; // 确保初始位置与实际宽度匹配
        } else {
            sidebar.style.right = '-300px'; // 默认宽度的对应位置
        }

        // 渲染高亮列表面板
        function renderHighlightsList() {
            const highlightsListContainer = sidebar.querySelector(`.${STYLE_PREFIX}highlights-list`);
            if (!highlightsListContainer) return;

            // 清空容器
            highlightsListContainer.innerHTML = '';
            Object.assign(highlightsListContainer.style, {
                height: 'calc(100vh - 120px)', // 调整合适高度,减去顶栏和标签栏高度
                overflow: 'hidden',
                display: 'flex',    // 添加flex布局
                flexDirection: 'column', // 确保子元素垂直排列
                paddingBottom: '0'  // 确保底部无padding
            });

            // 创建高亮列表
            const listContainer = document.createElement('div');
            listContainer.className = `${STYLE_PREFIX}highlights-items`;
            Object.assign(listContainer.style, {
                display: 'flex',
                flexDirection: 'column',
                gap: '8px',
                height: 'calc(100% - 22px)', // 从12px调整到22px,给上移的底部按钮腾出额外空间
                overflow: 'auto',
                paddingRight: '8px',
                paddingBottom: '4px' // 已经是5px,保持不变
            });

            // 自定义滚动条样式
            const styleEl = document.createElement('style');
            styleEl.textContent = `
                .${STYLE_PREFIX}highlights-items::-webkit-scrollbar {
                    width: 5px; /* 更细的滚动条 */
                }
                .${STYLE_PREFIX}highlights-items::-webkit-scrollbar-track {
                    background: rgba(255, 255, 255, 0.03); /* 更微妙的轨道 */
                    border-radius: 3px;
                }
                .${STYLE_PREFIX}highlights-items::-webkit-scrollbar-thumb {
                    background: rgba(255, 255, 255, 0.15); /* 更微妙的滑块 */
                    border-radius: 3px;
                }
                .${STYLE_PREFIX}highlights-items::-webkit-scrollbar-thumb:hover {
                    background: rgba(255, 255, 255, 0.25);
                }
            `;
            document.head.appendChild(styleEl);

            // 排序高亮,按时间倒序
            const sortedHighlights = [...highlights].sort((a, b) => (b.timestamp || 0) - (a.timestamp || 0));

            if (sortedHighlights.length === 0) {
                // 显示空状态
                const emptyState = document.createElement('div');
                Object.assign(emptyState.style, {
                    display: 'flex',
                    flexDirection: 'column',
                    alignItems: 'center',
                    justifyContent: 'center',
                    padding: '60px 20px',
                    textAlign: 'center',
                    color: '#999',
                    fontSize: '14px'
                });

                // 使用SVG图标作为空状态图标
                emptyState.innerHTML = `
                    <svg width="60" height="60" viewBox="0 0 24 24" fill="none" stroke="rgba(255,255,255,0.15)"
                        stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path>
                    </svg>
                    <p style="margin-top:16px;">暂无高亮内容<br>选中文本并点击颜色进行高亮</p>
                `;
                listContainer.appendChild(emptyState);
            } else {
                // 渲染所有高亮项目
                sortedHighlights.forEach((highlight, index) => {
                    const highlightItem = createHighlightItem(highlight, index);
                    listContainer.appendChild(highlightItem);
                });
            }

            highlightsListContainer.appendChild(listContainer);

            // 创建底部固定按钮栏
            const bottomActionBar = document.createElement('div');
            bottomActionBar.className = `${STYLE_PREFIX}highlights-bottom-actions`;
            Object.assign(bottomActionBar.style, {
                display: 'flex',
                position: 'absolute',
                bottom: '0',
                left: '0',
                right: '0',
                padding: '10px 16px', // 调整内边距
                borderTop: '1px solid rgba(255, 255, 255, 0.06)', // 更微妙的分隔线
                background: 'rgba(26, 26, 32, 0.9)', // 半透明背景
                backdropFilter: 'blur(10px)', // 磨砂玻璃效果
                zIndex: '1',
                gap: '10px',
            });

            // 创建刷新按钮
            const refreshBtn = document.createElement('button');
            refreshBtn.textContent = '刷新列表';
            Object.assign(refreshBtn.style, {
                flex: '1',
                background: 'rgba(255, 255, 255, 0.06)', // 保持原来的背景色
                border: '1px solid rgba(255, 255, 255, 0.08)', // 保持原来的边框
                borderRadius: '4px',
                padding: '8px 12px', // 添加水平内边距与清除按钮一致
                color: '#e0e0e0',
                fontSize: '13px', // 增大字体与清除按钮一致
                fontWeight: '500',
                cursor: 'pointer', // 添加指针样式
                transition: 'all 0.2s ease' // 添加过渡效果
            });

            // 添加悬停效果
            refreshBtn.addEventListener('mouseenter', () => {
                refreshBtn.style.background = 'rgba(255, 255, 255, 0.15)';
            });
            refreshBtn.addEventListener('mouseleave', () => {
                refreshBtn.style.background = 'rgba(255, 255, 255, 0.06)';
            });

            refreshBtn.addEventListener('click', () => {
                // 刷新高亮列表
                loadHighlights();
                applyHighlights();
                renderHighlightsList();
            });

            // 创建清除按钮
            const clearBtn = document.createElement('button');
            clearBtn.textContent = '清除全部';
            Object.assign(clearBtn.style, {
                flex: '1',
                background: 'rgba(190, 60, 60, 0.8)', // 更和谐的深红色
                border: '1px solid rgba(190, 60, 60, 0.2)', // 淡化边框
                color: '#f5e0e0', // 更柔和的白色文字
                borderRadius: '4px',
                padding: '8px 12px',
                fontSize: '13px',
                fontWeight: '500',
                cursor: 'pointer',
                transition: 'all 0.2s ease'
            });

            // 添加悬停效果
            clearBtn.addEventListener('mouseenter', () => {
                clearBtn.style.background = 'rgba(205, 70, 70, 0.85)';
                clearBtn.style.color = '#f7e7e7';
            });
            clearBtn.addEventListener('mouseleave', () => {
                clearBtn.style.background = 'rgba(190, 60, 60, 0.8)';
                clearBtn.style.color = '#f5e0e0';
            });

            clearBtn.addEventListener('click', () => {
                if (highlights.length === 0) return;

                // 确认删除
                if (confirm('确定要删除所有高亮吗?此操作不可撤销。')) {
                    // 移除DOM中的高亮元素
                    document.querySelectorAll(`.${STYLE_PREFIX}highlight-marked`).forEach(el => {
                        const textNode = document.createTextNode(el.textContent);
                        el.parentNode.replaceChild(textNode, el);
                    });

                    // 清空高亮数组
                    highlights = [];
                    saveHighlights();
                    renderHighlightsList();
                }
            });

            bottomActionBar.appendChild(refreshBtn);
            bottomActionBar.appendChild(clearBtn);
            highlightsListContainer.appendChild(bottomActionBar);
        }

        updateSidebarHighlights = renderHighlightsList;

        // 创建单个高亮项目
        function createHighlightItem(highlight, index) {
            const item = document.createElement('div');
            item.className = `${STYLE_PREFIX}highlight-item`;
            item.dataset.highlightId = highlight.id;

            Object.assign(item.style, {
                backgroundColor: 'rgba(30, 30, 36, 0.6)', // 更深、更专业的卡片背景
                borderRadius: '5px', // 更小的圆角
                padding: '10px 12px', // 增加水平内边距
                position: 'relative',
                transition: 'all 0.2s cubic-bezier(0.1, 0.9, 0.2, 1)', // 更平滑的过渡动画
                border: '1px solid rgba(255, 255, 255, 0.04)', // 更微妙的边框
                backdropFilter: 'blur(8px)', // 添加磨砂玻璃效果 (现代浏览器)
            })

            // 颜色指示器
            const colorIndicator = document.createElement('div');
            Object.assign(colorIndicator.style, {
                position: 'absolute',
                top: '0',
                left: '0',
                width: '3px',
                height: '100%',
                backgroundColor: highlight.color,
                borderTopLeftRadius: '12px',
                borderBottomLeftRadius: '12px'
            });

            // 高亮内容
            const content = document.createElement('div');
            Object.assign(content.style, {
                paddingLeft: '3px',
                color: '#fff',
                fontSize: '14px',
                lineHeight: '1.4',
                marginBottom: '8px',
                wordBreak: 'break-word',
                display: '-webkit-box',
                WebkitBoxOrient: 'vertical',
                WebkitLineClamp: '2',
                overflow: 'hidden',
                textOverflow: 'ellipsis'
            });

            // 处理高亮文本,避免XSS
            const textNode = document.createTextNode(highlight.text);
            content.appendChild(textNode);

            // 底部信息栏
            const infoBar = document.createElement('div');
            Object.assign(infoBar.style, {
                display: 'flex',
                justifyContent: 'space-between',
                alignItems: 'center',
                fontSize: '12px',
                marginTop: '6px',
                paddingLeft: '3px'  // 与内容区域左边距统一
            });

            // 时间信息
            const timeInfo = document.createElement('div');
            Object.assign(timeInfo.style, {
                color: '#999',
                fontSize: '12px'
            });

            // 格式化时间
            const date = new Date(highlight.timestamp);
            const formattedDate = `${date.getMonth() + 1}月${date.getDate()}日 ${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
            timeInfo.textContent = formattedDate;

            // 操作按钮容器
            const actionButtons = document.createElement('div');
            Object.assign(actionButtons.style, {
                display: 'flex',
                gap: '10px'
            });

            // 跳转按钮
            const jumpButton = document.createElement('button');
            Object.assign(jumpButton.style, {
                background: 'none',
                border: 'none',
                padding: '3px',
                cursor: 'pointer',
                color: '#74b4ff',
                display: 'flex',
                alignItems: 'center',
                fontSize: '12px',
                transition: 'color 0.15s ease'
            });
            jumpButton.title = '跳转到此高亮';
            jumpButton.innerHTML = `
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                    stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <path d="M15 3h6v6M14 10l6.16-6.16M9 21H3v-6M10 14l-6.16 6.16"></path>
                </svg>
            `;

            jumpButton.addEventListener('mouseenter', () => {
                jumpButton.style.color = '#a0cfff';
            });

            jumpButton.addEventListener('mouseleave', () => {
                jumpButton.style.color = '#74b4ff';
            });

            jumpButton.addEventListener('click', (e) => {
                e.stopPropagation();
                scrollToHighlight(highlight.id);
            });

            // 删除按钮
            const deleteButton = document.createElement('button');
            Object.assign(deleteButton.style, {
                background: 'none',
                border: 'none',
                padding: '3px',
                cursor: 'pointer',
                color: 'rgba(190, 60, 60, 0.8)',
                display: 'flex',
                alignItems: 'center',
                fontSize: '12px',
                transition: 'color 0.15s ease'
            });
            deleteButton.title = '删除此高亮';
            deleteButton.innerHTML = `
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
                    stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"></path>
                </svg>
            `;

            deleteButton.addEventListener('mouseenter', () => {
                deleteButton.style.color = 'rgba(255, 80, 80, 0.95)'; // 更亮、更饱和的红色
            });

            deleteButton.addEventListener('mouseleave', () => {
                deleteButton.style.color = 'rgba(190, 60, 60, 0.8)'; // 恢复原来的颜色
            });

            deleteButton.addEventListener('click', (e) => {
                e.stopPropagation();
                removeHighlightById(highlight.id);
                item.style.opacity = '0';
                item.style.height = '0';
                item.style.padding = '0';
                item.style.margin = '0';
                item.style.overflow = 'hidden';

                setTimeout(() => {
                    renderHighlightsList();
                }, 300);
            });

            actionButtons.appendChild(jumpButton);
            actionButtons.appendChild(deleteButton);

            infoBar.appendChild(timeInfo);
            infoBar.appendChild(actionButtons);

            // 添加项目悬停效果
            item.addEventListener('mouseenter', () => {
                item.style.backgroundColor = 'rgba(40, 40, 50, 0.75)'; // 更微妙的变化
                item.style.transform = 'translateY(-2px)'; // 轻微上浮
                item.style.boxShadow = '0 4px 12px rgba(0, 0, 0, 0.2), 0 1px 3px rgba(0, 0, 0, 0.1)'; // 分层阴影
            });
            item.addEventListener('mouseleave', () => {
                item.style.backgroundColor = 'rgba(0, 0, 0, 0.2)';
                item.style.transform = 'translateY(0)';
                item.style.boxShadow = 'none';
            });

            item.appendChild(colorIndicator);
            item.appendChild(content);
            item.appendChild(infoBar);

            return item;
        }

        // 滚动到指定高亮
        function scrollToHighlight(highlightId) {
            const highlightElement = document.querySelector(`.${STYLE_PREFIX}highlight-marked[data-highlight-id="${highlightId}"]`);
            if (highlightElement) {
                // 平滑滚动到元素
                highlightElement.scrollIntoView({ behavior: 'smooth', block: 'center' });

                // 添加闪烁效果,并设置临时样式使其更加明显
                highlightElement.classList.add(`${STYLE_PREFIX}highlight-flash`);

                // 保存原有的样式以便恢复
                const originalTransition = highlightElement.style.transition;

                // 添加过渡效果使视觉反馈更平滑
                highlightElement.style.transition = 'all 0.3s ease';

                setTimeout(() => {
                    highlightElement.classList.remove(`${STYLE_PREFIX}highlight-flash`);
                    highlightElement.style.transition = originalTransition;
                }, 2500);
            }
        }

        // 初始渲染高亮列表
        renderHighlightsList();

        // 渲染禁用管理面板内容
        function renderDisabledPanel() {
            const container = sidebar.querySelector(`.${STYLE_PREFIX}disabled-container`);
            if (!container) return;

            // 清空容器
            container.innerHTML = '';

            // 添加当前页面管理区域
            const currentPageSection = document.createElement('div');
            currentPageSection.className = `${STYLE_PREFIX}disabled-section`;
            Object.assign(currentPageSection.style, {
                marginBottom: '20px'
            });

            const currentPageTitle = document.createElement('div');
            currentPageTitle.className = `${STYLE_PREFIX}disabled-title`;
            currentPageTitle.innerHTML = `<span>当前页面</span>`;
            Object.assign(currentPageTitle.style, {
                fontSize: '14px',
                fontWeight: '600',
                color: '#eee',
                marginBottom: '10px',
                display: 'flex',
                alignItems: 'center',
                gap: '8px'
            });

            // 当前页面状态
            const currentStatus = document.createElement('div');
            currentStatus.className = `${STYLE_PREFIX}current-status`;
            currentStatus.innerHTML = renderCurrentPageStatus();

            currentPageSection.appendChild(currentPageTitle);
            currentPageSection.appendChild(currentStatus);
            container.appendChild(currentPageSection);

            // 禁用域名列表区域
            const domainsSection = document.createElement('div');
            domainsSection.className = `${STYLE_PREFIX}disabled-section`;
            Object.assign(domainsSection.style, {
                marginBottom: '20px'
            });

            const domainsTitle = document.createElement('div');
            domainsTitle.className = `${STYLE_PREFIX}disabled-title`;
            domainsTitle.innerHTML = `<span>禁用域名列表</span>`;
            Object.assign(domainsTitle.style, {
                fontSize: '14px',
                fontWeight: '600',
                color: '#eee',
                marginBottom: '10px',
                display: 'flex',
                alignItems: 'center',
                gap: '8px'
            });

            const domainsList = document.createElement('div');
            domainsList.className = `${STYLE_PREFIX}domains-list`;
            domainsList.innerHTML = renderDisabledDomains();

            // 添加域名表单
            const addDomainForm = document.createElement('div');
            addDomainForm.className = `${STYLE_PREFIX}add-disabled-form`;
            Object.assign(addDomainForm.style, {
                display: 'flex',
                marginTop: '12px',
                gap: '0'
            });

            const domainInput = document.createElement('input');
            domainInput.className = `${STYLE_PREFIX}add-disabled-input`;
            domainInput.id = 'add-domain-input';
            domainInput.placeholder = '输入域名...';
            Object.assign(domainInput.style, {
                flex: '1',
                backgroundColor: 'rgba(255, 255, 255, 0.07)',
                border: '1px solid rgba(255, 255, 255, 0.1)',
                borderRadius: '4px 0 0 4px',
                padding: '8px 12px',
                fontSize: '13px',
                color: '#fff',
                outline: 'none'
            });

            const addDomainBtn = document.createElement('button');
            addDomainBtn.className = `${STYLE_PREFIX}add-disabled-button`;
            addDomainBtn.id = 'add-domain-btn';
            addDomainBtn.textContent = '添加';
            Object.assign(addDomainBtn.style, {
                backgroundColor: 'rgba(190, 60, 60, 0.8)',
                color: '#f5e0e0',
                border: 'none',
                borderRadius: '0 4px 4px 0',
                padding: '8px 16px',
                fontSize: '13px',
                fontWeight: '500',
                cursor: 'pointer',
                transition: 'all 0.2s ease'
            });

            addDomainForm.appendChild(domainInput);
            addDomainForm.appendChild(addDomainBtn);

            domainsSection.appendChild(domainsTitle);
            domainsSection.appendChild(domainsList);
            domainsSection.appendChild(addDomainForm);
            container.appendChild(domainsSection);

            // 禁用URL列表区域
            const urlsSection = document.createElement('div');
            urlsSection.className = `${STYLE_PREFIX}disabled-section`;

            const urlsTitle = document.createElement('div');
            urlsTitle.className = `${STYLE_PREFIX}disabled-title`;
            urlsTitle.innerHTML = `<span>禁用网址列表</span>`;
            Object.assign(urlsTitle.style, {
                fontSize: '14px',
                fontWeight: '600',
                color: '#eee',
                marginBottom: '10px',
                display: 'flex',
                alignItems: 'center',
                gap: '8px'
            });

            const urlsList = document.createElement('div');
            urlsList.className = `${STYLE_PREFIX}urls-list`;
            urlsList.innerHTML = renderDisabledUrls();

            // 添加URL表单
            const addUrlForm = document.createElement('div');
            addUrlForm.className = `${STYLE_PREFIX}add-disabled-form`;
            Object.assign(addUrlForm.style, {
                display: 'flex',
                marginTop: '12px',
                gap: '0'
            });

            const urlInput = document.createElement('input');
            urlInput.className = `${STYLE_PREFIX}add-disabled-input`;
            urlInput.id = 'add-url-input';
            urlInput.placeholder = '输入网址...';
            Object.assign(urlInput.style, {
                flex: '1',
                backgroundColor: 'rgba(255, 255, 255, 0.07)',
                border: '1px solid rgba(255, 255, 255, 0.1)',
                borderRadius: '4px 0 0 4px',
                padding: '8px 12px',
                fontSize: '13px',
                color: '#fff',
                outline: 'none'
            });

            const addUrlBtn = document.createElement('button');
            addUrlBtn.className = `${STYLE_PREFIX}add-disabled-button`;
            addUrlBtn.id = 'add-url-btn';
            addUrlBtn.textContent = '添加';
            Object.assign(addUrlBtn.style, {
                backgroundColor: 'rgba(190, 60, 60, 0.8)',
                color: '#f5e0e0',
                border: 'none',
                borderRadius: '0 4px 4px 0',
                padding: '8px 16px',
                fontSize: '13px',
                fontWeight: '500',
                cursor: 'pointer',
                transition: 'all 0.2s ease'
            });

            addUrlForm.appendChild(urlInput);
            addUrlForm.appendChild(addUrlBtn);

            urlsSection.appendChild(urlsTitle);
            urlsSection.appendChild(urlsList);
            urlsSection.appendChild(addUrlForm);
            container.appendChild(urlsSection);

            // 绑定事件
            bindDisabledPanelEvents();
        }

        // 渲染当前页面状态
        function renderCurrentPageStatus() {
            const isDomainDisabled = disabledList.domains.includes(currentDomain);
            const isUrlDisabled = disabledList.urls.includes(currentPageUrl);

            if (isDomainDisabled || isUrlDisabled) {
                return `
                    <div class="${STYLE_PREFIX}disabled-item">
                        <div class="${STYLE_PREFIX}disabled-info">
                            <span>${isDomainDisabled ? `此域名 (${currentDomain}) 已禁用高亮` : '此网址已禁用高亮'}</span>
                        </div>
                        <span class="${STYLE_PREFIX}disabled-action" data-type="${isDomainDisabled ? 'domain' : 'url'}" data-value="${isDomainDisabled ? currentDomain : currentPageUrl}">
                            启用
                        </span>
                    </div>
                `;
            } else {
                return `
                    <div class="${STYLE_PREFIX}current-page-actions">
                        <button class="${STYLE_PREFIX}disable-btn" id="disable-domain-btn">
                            禁用此域名
                        </button>
                        <button class="${STYLE_PREFIX}disable-btn" id="disable-url-btn">
                            禁用此网址
                        </button>
                    </div>
                `;
            }
        }

        // 渲染禁用域名列表
        function renderDisabledDomains() {
            if (disabledList.domains.length === 0) {
                return `<div class="${STYLE_PREFIX}empty-list">没有禁用的域名</div>`;
            }

            return disabledList.domains.map(domain => `
                <div class="${STYLE_PREFIX}disabled-item">
                    <div class="${STYLE_PREFIX}disabled-info">
                        <span>${domain}</span>
                    </div>
                    <span class="${STYLE_PREFIX}disabled-action" data-type="domain" data-value="${domain}">
                        删除
                    </span>
                </div>
            `).join('');
        }


        // 渲染禁用URL列表
        function renderDisabledUrls() {
            if (disabledList.urls.length === 0) {
                return `<div class="${STYLE_PREFIX}empty-list">没有禁用的网址</div>`;
            }

            return disabledList.urls.map(url => {
                // 为了美观,截断过长的URL
                const displayUrl = url.length > 40 ? url.substring(0, 37) + '...' : url;

                return `
                    <div class="${STYLE_PREFIX}disabled-item" title="${url}">
                        <div class="${STYLE_PREFIX}disabled-info">
                            <span>${displayUrl}</span>
                        </div>
                        <span class="${STYLE_PREFIX}disabled-action" data-type="url" data-value="${url}">
                            删除
                        </span>
                    </div>
                `;
            }).join('');
        }

        // 绑定禁用管理面板事件
        function bindDisabledPanelEvents() {
            // 禁用当前域名按钮
            const disableDomainBtn = document.getElementById('disable-domain-btn');
            if (disableDomainBtn) {
                disableDomainBtn.addEventListener('click', () => {
                    if (confirm(`确定要禁用域名 "${currentDomain}" 上的高亮功能吗?`)) {
                        disableDomain(currentDomain);
                        renderDisabledPanel();
                    }
                });
            }

            // 禁用当前网址按钮
            const disableUrlBtn = document.getElementById('disable-url-btn');
            if (disableUrlBtn) {
                disableUrlBtn.addEventListener('click', () => {
                    if (confirm('确定要禁用当前网址的高亮功能吗?')) {
                        disableUrl(currentPageUrl);
                        renderDisabledPanel();
                    }
                });
            }

            // 添加样式
            const styleSheet = document.createElement('style');
            styleSheet.textContent = `
                .${STYLE_PREFIX}disabled-item {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    padding: 8px 12px; // 增加水平内边距
                    background-color: rgba(40, 40, 50, 0.4); // 更深的背景
                    border-radius: 4px;
                    margin-bottom: 6px; // 减少垂直间距
                    transition: all 0.2s ease;
                    border: 1px solid rgba(255, 255, 255, 0.03); // 添加微妙的边框
                }

                .${STYLE_PREFIX}disabled-item:hover {
                    background-color: rgba(60, 60, 70, 0.4); // 更微妙的悬停效果
                    transform: translateX(2px); // 添加轻微的位移感
                }

                .${STYLE_PREFIX}disabled-info {
                    display: flex;
                    align-items: center;
                    gap: 8px;
                    font-size: 13px;
                    color: #ddd;
                    flex: 1;
                    overflow: hidden;
                    text-overflow: ellipsis;
                    white-space: nowrap;
                }

                .${STYLE_PREFIX}disabled-action {
                    color: #ff8f8f;
                    font-size: 12px;
                    cursor: pointer;
                    padding: 2px 6px;
                    border-radius: 3px;
                    transition: all 0.2s;
                    opacity: 0.8;
                }

                .${STYLE_PREFIX}disabled-action:hover {
                    background-color: rgba(255, 82, 82, 0.15); // 更和谐的悬停效果
                    opacity: 1; // 悬停时完全不透明
                }

                .${STYLE_PREFIX}empty-list {
                    padding: 10px;
                    color: #888;
                    font-style: italic;
                    font-size: 13px;
                    text-align: center;
                    background-color: rgba(0, 0, 0, 0.15);
                    border-radius: 4px;
                }

                .${STYLE_PREFIX}current-page-actions {
                    display: flex;
                    gap: 10px;
                }

                .${STYLE_PREFIX}disable-btn {
                    flex: 1;
                    background: rgba(255, 255, 255, 0.08);
                    border: none;
                    border-radius: 4px;
                    padding: 8px 12px;
                    color: #e0e0e0;
                    font-size: 14px;
                    font-weight: 500;
                    cursor: pointer;
                    transition: all 0.2s ease;
                }

                .${STYLE_PREFIX}disable-btn:hover {
                    background-color: rgba(255, 255, 255, 0.15);
                }

                .${STYLE_PREFIX}add-disabled-input:focus {
                    border-color: #74b4ff;
                    background-color: rgba(255, 255, 255, 0.1);
                }

                .${STYLE_PREFIX}add-disabled-button:hover {
                    background-color: rgba(205, 70, 70, 0.85);
                    color: #f7e7e7;
                }
            `;
            document.head.appendChild(styleSheet);

            // 删除按钮事件
            document.querySelectorAll(`.${STYLE_PREFIX}disabled-action`).forEach(btn => {
                btn.addEventListener('click', (e) => {
                    const type = e.target.dataset.type;
                    const value = e.target.dataset.value;

                    if (e.target.textContent.trim() === '删除') {
                        if (type === 'domain') {
                            disabledList.domains = disabledList.domains.filter(d => d !== value);
                        } else if (type === 'url') {
                            disabledList.urls = disabledList.urls.filter(u => u !== value);
                        }
                        saveDisabledList();
                        renderDisabledPanel();
                    } else if (e.target.textContent.trim() === '启用') {
                        if (type === 'domain') {
                            enableDomain(value);
                        } else if (type === 'url') {
                            enableUrl(value);
                        }
                        renderDisabledPanel();
                    }
                });
            });

            // 添加域名按钮
            const addDomainBtn = document.getElementById('add-domain-btn');
            if (addDomainBtn) {
                addDomainBtn.addEventListener('click', () => {
                    const input = document.getElementById('add-domain-input');
                    const domain = input.value.trim();

                    if (domain) {
                        if (!disabledList.domains.includes(domain)) {
                            disabledList.domains.push(domain);
                            saveDisabledList();
                            input.value = '';
                            renderDisabledPanel();
                        } else {
                            alert('该域名已在禁用列表中');
                        }
                    }
                });
            }

            // 添加URL按钮
            const addUrlBtn = document.getElementById('add-url-btn');
            if (addUrlBtn) {
                addUrlBtn.addEventListener('click', () => {
                    const input = document.getElementById('add-url-input');
                    const url = input.value.trim();

                    if (url) {
                        if (!disabledList.urls.includes(url)) {
                            disabledList.urls.push(url);
                            saveDisabledList();
                            input.value = '';
                            renderDisabledPanel();
                        } else {
                            alert('该网址已在禁用列表中');
                        }
                    }
                });
            }

            // 输入框回车事件
            const domainInput = document.getElementById('add-domain-input');
            if (domainInput) {
                domainInput.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter') {
                        document.getElementById('add-domain-btn').click();
                    }
                });
            }

            const urlInput = document.getElementById('add-url-input');
            if (urlInput) {
                urlInput.addEventListener('keydown', (e) => {
                    if (e.key === 'Enter') {
                        document.getElementById('add-url-btn').click();
                    }
                });
            }
        }

        // 初始渲染禁用管理面板
        renderDisabledPanel();
    }

    function init() {
        loadHighlights();
        registerEvents();
        if (document.readyState === 'complete') {
            setTimeout(() => {
                applyHighlights();
                observeDomChanges();
            }, 500);
        } else {
            window.addEventListener('load', () => {
                setTimeout(() => {
                    applyHighlights();
                    observeDomChanges();
                }, 500);
            });
        }
        // 注册油猴菜单命令
        GM_registerMenuCommand('打开侧边栏', () => {
            toggleSidebar(true);
        });
        GM_registerMenuCommand('切换浮动按钮显示/隐藏', toggleFloatingButton);
    }

    init();
    createFloatingButtonAndSidebar();
})();