Greasy Fork is available in English.

网页划词高亮工具

提供网页划词高亮功能

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

(function () {
    'use strict';

    // 全局变量
    let highlights = [];
    let currentPageUrl = window.location.href.split('#')[0];
    let currentDomain = window.location.hostname;
    let settings = GM_getValue('highlight_settings', {
        triggerMode: 'auto', // auto, rightClick, hotkey
        minTextLength: 1, // 修改默认最小触发长度为1
        colors: ['#ff909c', '#b89fff', '#74b4ff', '#70d382', '#ffcb7e'],
        activeColor: '#ff909c',
        sidebarPinned: false, // 添加侧边栏固定状态设置
        sidebarDescription: '高亮工具', // 添加侧边栏描述文本设置
        sidebarWidth: 320, // 添加侧边栏宽度设置,默认320px
        showFloatingButton: true // 新增:控制浮动按钮是否显示
    });

    // 全局变量 - 侧边栏固定状态
    let sidebarPinned = settings.sidebarPinned || false;

    // 禁用列表
    let disabledList = GM_getValue('disabled_list', {
        domains: [],
        urls: []
    });

    // 检查当前页面是否禁用高亮功能
    let isHighlightDisabled = disabledList.domains.includes(currentDomain) ||
        disabledList.urls.includes(currentPageUrl);

    // 防抖变量改进
    let menuDisplayTimer = null;
    let lastMenuDisplayTime = 0;
    let menuAnimating = false; // 菜单动画状态标记
    let ignoreNextClick = false; // 忽略下一次点击的标志
    let isProcessingColorClick = false; // 状态变量来控制点击处理

    // 侧边栏状态
    let sidebarOpen = false;

    GM_addStyle(`
        /* ====================
         * 1. 高亮菜单样式
         * ==================== */
        /* 高亮菜单容器 */
        .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; /* 隐藏时不响应事件 */
        }
        .highlight-menu.show {
            opacity: 1;
            pointer-events: auto; /* 显示时响应事件 */
        }
        
        /* 菜单箭头样式 */
        .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;
        }
        .highlight-menu.arrow-top::after {
            top: -6px; /* 减小间隙 */
            bottom: auto;
            /* 颠倒三角形方向 */
            clip-path: polygon(0 100%, 100% 100%, 50% 0);
        }
        
        /* 颜色选择区域 */
        .highlight-menu-colors {
            display: flex;
            flex-direction: row;
            align-items: center;
            margin: 0 2px; /* 减少外边距让色块更接近菜单边缘 */
            flex-wrap: nowrap; /* 确保颜色不会换行 */
            flex: 0 0 auto; /* 防止颜色区域被压缩 */
        }
        
        /* 颜色选择按钮 */
        .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; /* 防止颜色球被压缩 */
        }
        .highlight-menu-color:hover {
            transform: scale(1.12);
        }
        .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;
        }
        
        /* 菜单按钮通用样式 */
        .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; /* 防止按钮被压缩 */
        }
        .highlight-menu-action:hover {
            background: rgba(255,255,255,0.2);
        }
        
        /* 删除按钮样式 */
        .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; /* 增加与颜色区域的间距 */
        }
        .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);
        }
        .highlight-action-delete:active {
            transform: translateY(0px);
            background: rgba(255,82,82,0.2);
        }
    
        /* ====================
         * 2. 高亮标记样式
         * ==================== */
        /* 高亮显示的文本 */
        .highlight-marked {
            position: relative;
            cursor: pointer;
            border-radius: 2px;
            transition: opacity 0.15s ease;
        }
        .highlight-marked:hover {
            opacity: 0.9;
        }
        
        /* 闪烁效果用于高亮跳转 */
        @keyframes highlightFlash {
            0%, 100% { background-color: inherit; }
            50% { background-color: rgba(255, 255, 0, 0.5); }
        }
        .highlight-flash {
            animation: highlightFlash 1s ease 2;
        }
        
        /* 高亮错误恢复样式 */
        @keyframes fadeInOut {
            0%, 100% { opacity: 0.3; }
            50% { opacity: 1; }
        }
        .highlight-error-recovery {
            animation: fadeInOut 1.5s ease infinite;
            border: 2px dashed #ff6b6b !important;
        }
    
        /* ====================
         * 3. 工具栏按钮样式
         * ==================== */
        /* 浮动工具栏按钮 */
        .highlight-toolbar {
            position: fixed;
            bottom: 20px;
            right: 20px;
            background: rgba(51, 51, 54, 0.85);
            color: #fff;
            border-radius: 50%;
            width: 36px;
            height: 36px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 3px 16px rgba(0,0,0,0.3);
            cursor: pointer;
            z-index: 9998;
            transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s;
            user-select: none;
            touch-action: none;
            backdrop-filter: blur(4px);
        }
        .highlight-toolbar:hover {
            transform: scale(1.05);
            box-shadow: 0 4px 20px rgba(0,0,0,0.3);
            background: rgba(51, 51, 54, 1);
        }
        .highlight-toolbar:active {
            transform: scale(0.97);
        }
        
        /* 拖动时的样式 */
        .highlight-toolbar.dragging {
            opacity: 0.8;
            transform: scale(1.1);
            box-shadow: 0 8px 24px rgba(0,0,0,0.4);
            cursor: grabbing; /* 只在拖动时显示抓取图标 */
        }
        
        /* ====================
         * 4. 设置弹窗样式
         * ==================== */
        /* 设置弹窗容器 */
        .highlight-settings {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: #fff;
            border-radius: 16px;
            box-shadow: 0 8px 30px rgba(0,0,0,0.2);
            padding: 22px;
            z-index: 10000;
            display: none;
            min-width: 300px;
            max-width: 360px;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
        }
        .highlight-settings h3 {
            margin-top: 0;
            color: #333;
            font-weight: 500;
            margin-bottom: 16px;
            font-size: 17px;
        }
        
        /* 设置表单元素 */
        .highlight-settings label {
            display: block;
            margin: 12px 0 4px;
            font-weight: 500;
            color: #444;
            font-size: 14px;
        }
        .highlight-settings select,
        .highlight-settings input {
            width: 100%;
            padding: 8px 10px;
            border: 1px solid #e0e0e0;
            border-radius: 8px;
            font-size: 14px;
            color: #333;
            background: #f9f9f9;
        }
        .highlight-settings select:focus,
        .highlight-settings input:focus {
            outline: none;
            border-color: #90caf9;
            box-shadow: 0 0 0 2px rgba(144,202,249,0.2);
        }
        
        /* 设置按钮区域 */
        .highlight-settings-buttons {
            display: flex;
            gap: 8px;
            margin-top: 20px;
        }
        .highlight-settings button {
            padding: 8px 14px;
            border: none;
            border-radius: 8px;
            background: #2196f3;
            color: white;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.15s ease;
            font-size: 13px;
            flex: 1;
        }
        .highlight-settings button:hover {
            background: #1976d2;
        }
        .highlight-settings #clearHighlights {
            background: #f5f5f5;
            color: #e53935;
            border: 1px solid #e0e0e0;
        }
        .highlight-settings #clearHighlights:hover {
            background: #ffebee;
            border-color: #ffcdd2;
        }
        .highlight-settings #closeSettings {
            background: #f5f5f5;
            color: #616161;
            border: 1px solid #e0e0e0;
        }
        .highlight-settings #closeSettings:hover {
            background: #eeeeee;
            border-color: #bdbdbd;
        }
        
        /* 颜色设置区域 */
        .highlight-colors-setting {
            display: flex;
            flex-wrap: wrap;
            gap: 8px;
            margin-top: 8px;
        }
        .highlight-colors-setting .highlight-menu-color {
            width: 24px;
            height: 24px;
            box-shadow: 0 1px 5px rgba(0,0,0,0.2);
            border: 2px solid rgba(255,255,255,0.1);
        }
        .highlight-colors-setting .highlight-menu-color.active {
            box-shadow: 0 0 0 2px #ff5252;
            border-color: rgba(255,255,255,0.5);
            transform: scale(1.1);
        }
        
        /* ====================
         * 5. 消息提示样式
         * ==================== */
        /* 通知提示框 */
        .highlight-toast {
            position: fixed;
            bottom: 80px;
            right: 20px;
            background: #333;
            color: #fff;
            padding: 10px 20px;
            border-radius: 4px;
            z-index: 10001;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            font-size: 14px;
            box-shadow: 0 2px 8px rgba(0,0,0,0.2);
            opacity: 0;
            transform: translateY(10px);
            transition: opacity 0.3s, transform 0.3s;
        }
        .highlight-toast.show {
            opacity: 1;
            transform: translateY(0);
        }
        .highlight-toast.success {
            background: #4caf50;
        }
        .highlight-toast.error {
            background: #f44336;
        }
        .highlight-toast.warning {
            background: #ff9800;
        }

        /* ====================
         * 6. 侧边栏基本结构
         * ==================== */
        /* 侧边栏容器 */
        .highlight-sidebar {
            position: fixed;
            top: 0;
            right: calc(-1 * var(--sidebar-width, 320px));
            width: var(--sidebar-width, 320px);
            height: 100%;
            background: #333336;
            color: #e0e0e0;
            box-shadow: -2px 0 15px rgba(0,0,0,0.4);
            z-index: 10000;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
            transition: right 0.3s ease;
            display: flex;
            flex-direction: column;
            overflow: hidden;
            border-left: 1px solid rgba(255,255,255,0.05);
            min-width: 250px;
            max-width: 1600px;
        }
        .highlight-sidebar.open {
            right: 0;
        }
        
        /* 侧边栏拖动手柄 */
        .sidebar-resizer {
            position: absolute;
            left: 0;
            top: 0;
            width: 6px;
            height: 100%;
            background: transparent;
            cursor: ew-resize;
            z-index: 10001;
            transition: background-color 0.2s, box-shadow 0.2s;
        }
        .sidebar-resizer:hover,
        .sidebar-resizer.dragging {
            background-color: rgba(255,82,82,0.3);
        }
        .sidebar-resizer.min-width,
        .sidebar-resizer.max-width {
            background-color: rgba(255,82,82,0.5) !important;
            box-shadow: 0 0 8px rgba(255,82,82,0.8);
        }
        
        /* ====================
         * 7. 侧边栏标题栏
         * ==================== */
        /* 侧边栏标题栏容器 */
        .sidebar-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 6px 10px;
            min-height: 28px;
            background: rgba(0,0,0,0.25);
            border-bottom: 1px solid rgba(255,255,255,0.05);
        }
        
        /* 左侧描述区域 */
        .sidebar-description {
            /* 文本样式 */
            font-size: 12px;
            color: #e0e0e0;
            font-weight: 500;
            letter-spacing: 0.3px;
            
            /* 文本处理 */
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            max-width: 85%; /* 使用最大的占比值 */
            
            /* 编辑相关样式 */
            cursor: pointer;
            transition: all 0.2s;
            border-bottom: 1px dashed transparent;
            padding-bottom: 2px;
        }
        .sidebar-description:hover {
            border-bottom-color: rgba(255, 255, 255, 0.3);
        }
        .sidebar-description::after {
            content: '✎';
            opacity: 0;
            margin-left: 5px;
            font-size: 12px;
            transition: opacity 0.2s;
        }
        .sidebar-description:hover::after {
            opacity: 0.7;
        }
        .sidebar-description.editing {
            border: none;
            background: rgba(255,255,255,0.1);
            padding: 2px 8px;
            border-radius: 4px;
            outline: none;
        }
        .sidebar-description.editing::after {
            content: '';
        }
        
        /* 右侧按钮组 */
        .sidebar-controls {
            display: flex;
            gap: 4px; /* 使用最小的间距 */
            align-items: center; /* 确保按钮垂直居中 */
        }
        
        /* 通用按钮样式 */
        .sidebar-btn {
            cursor: pointer;
            color: #e0e0e0;
            width: 22px; /* 使用紧凑型设计尺寸 */
            height: 22px;
            border-radius: 3px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.2s ease;
            background: rgba(255,255,255,0.08);
            position: relative;
            overflow: hidden;
            flex-shrink: 0; /* 防止按钮被压缩 */
            padding: 0; /* 移除任何内边距 */
            box-sizing: border-box; /* 确保边框计入总尺寸 */
        }
        .sidebar-btn:hover {
            background: rgba(255,255,255,0.15);
            color: #fff;
        }
        .sidebar-btn:active {
            transform: none; /* 取消按下的位移效果 */
        }
        .sidebar-btn svg {
            width: 16px;
            height: 16px;
            transition: color 0.2s ease;
            display: block;
            margin: 0;
            vertical-align: middle;
        }
        
        /* 固定按钮样式 */
        .sidebar-pin {
            position: relative;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .sidebar-pin svg {
            display: block;
            margin: 0 auto;
            transform-origin: center;
            transition: transform 0.3s ease;
        }
        .sidebar-pin.pinned {
            background: rgba(255, 82, 82, 0.15);
            color: #ff5252;
        }
        .sidebar-pin.pinned svg {
            transform: none; /* 移除旋转效果 */
            filter: drop-shadow(0 1px 1px rgba(0,0,0,0.2));
        }
        .sidebar-pin.pinned:hover {
            background: rgba(255, 82, 82, 0.25);
        }
        
        /* 关闭按钮样式 */
        .sidebar-close {
            font-size: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            padding-bottom: 2px;
        }
        .sidebar-close span {
            line-height: 1;
            display: block;
        }
        .sidebar-close:hover {
            background: rgba(255,82,82,0.15);
            color: #ff5252;
        }
        .sidebar-close:hover svg {
            transform: none; /* 移除旋转动画效果 */
        }
        .sidebar-close svg {
            margin: 0;
            position: relative;
            top: 0;
        }
        
        /* ====================
         * 8. 侧边栏内容区
         * ==================== */
        /* 内容区容器 */
        .sidebar-content {
            flex: 1;
            overflow-y: auto;
            padding: 0;
            padding-bottom: 15px; /* 确保底部内容不被遮挡 */
        }
        
        /* 选项卡导航样式 */
        .sidebar-tabs {
            display: flex;
            background: rgba(0,0,0,0.15);
            border-bottom: none;
            margin-bottom: 0;
            padding: 0;
            height: 36px;
            align-items: stretch;
        }
        .sidebar-tab {
            padding: 0;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            letter-spacing: 0.3px;
            color: #aaa;
            font-weight: 500;
            height: 36px;
            border-bottom: 2px solid transparent;
            transition: all 0.2s;
            flex-grow: 1;
            text-align: center;
            cursor: pointer;
        }
        .sidebar-tab:hover {
            color: #fff;
            background-color: rgba(255,255,255,0.05);
        }
        .sidebar-tab.active {
            color: #fff;
            border-bottom-color: #ff5252;
            background-color: rgba(255,82,82,0.1);
            font-weight: 600;
        }
        
        /* 选项卡内容样式 */
        .tab-content {
            display: none;
            padding: 10px;
        }
        .tab-content.active {
            display: block;
        }
        
        /* 特殊的高亮列表tab样式 */
        #tab-highlights.active {
            display: flex !important; 
            flex-direction: column;
            height: 100%;
            padding: 10px 10px 0 10px;
            box-sizing: border-box;
        }
        
        /* 标签页标题样式 */
        .tab-content h3 {
            font-size: 13px;
            font-weight: 600;
            color: #fff;
            margin: 12px 0 8px;
            padding-bottom: 6px;
            border-bottom: 1px solid rgba(255,255,255,0.1);
        }
        .tab-content h3:first-child {
            margin-top: 5px;
        }
        
        /* ====================
         * 9. 设置页面元素
         * ==================== */
        /* 设置面板的样式调整 */
        .sidebar-settings label {
            display: block;
            margin: 10px 0 4px;
            font-weight: 500;
            color: #e0e0e0;
            font-size: 12px;
        }
        .sidebar-settings select:focus,
        .sidebar-settings input:focus,
        .add-disabled-input:focus {
            outline: none;
            border-color: rgba(255,82,82,0.5);
            box-shadow: 0 0 0 2px rgba(255,82,82,0.2);
            background: rgba(255,255,255,0.09);
        }
        
        /* Chrome/Safari 特定样式 - 使用::-webkit-scrollbar来美化下拉框的滚动条 */
        .sidebar-settings select::-webkit-scrollbar {
            width: 8px;
        }
        .sidebar-settings select::-webkit-scrollbar-track {
            background: #222224;
        }
        .sidebar-settings select::-webkit-scrollbar-thumb {
            background-color: #666;
            border-radius: 4px;
        }
        
        /* 下拉选项的样式 - 针对支持的浏览器 */
        .sidebar-settings select option {
            background-color: #333336;
            color: #e0e0e0;
            padding: 10px 15px;
        }
        
        /* 下拉选项悬停效果 */
        .sidebar-settings select option:hover {
            background-color: #444448;
        }

        .sidebar-settings select,
        .sidebar-settings input[type="text"],
        .sidebar-settings input[type="number"] {
            background: rgba(255,255,255,0.06);
            color: #e0e0e0;
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 4px;
            width: 100%;
            padding: 7px 10px;
            box-sizing: border-box;
            font-size: 12px;
        }

        /* ====================
         * 10. 高亮列表样式
         * ==================== */
        /* 高亮列表容器 */
        .highlight-list {
            margin-top: 8px;
        }
        
        /* 高亮列表tab中特殊样式 */
        #tab-highlights .highlight-list {
            flex: 1;
            overflow-y: auto;
            margin-bottom: 0;
            padding-right: 4px;
            scrollbar-width: thin;
            scrollbar-color: rgba(255,255,255,0.1) transparent;
        }
        
        /* 自定义滚动条样式 */
        #tab-highlights .highlight-list::-webkit-scrollbar {
            width: 4px; /* 极细滚动条 */
        }
        #tab-highlights .highlight-list::-webkit-scrollbar-track {
            background: transparent; /* 透明轨道 */
        }
        #tab-highlights .highlight-list::-webkit-scrollbar-thumb {
            background-color: transparent; /* 完全透明滚动条滑块 */
            border-radius: 4px;
        }
        #tab-highlights .highlight-list::-webkit-scrollbar-thumb:hover {
            background-color: transparent; /* 悬停时保持透明 */
        }
        
        /* 高亮列表项样式 */
        .highlight-list-item {
            padding: 8px 10px;
            margin-bottom: 6px;
            border-radius: 6px;
            cursor: pointer;
            transition: transform 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
            position: relative;
            border-left: 3px solid;  /* 颜色在行内样式中设置 */
            background: rgba(255,255,255,0.06);
            box-shadow: 0 1px 3px rgba(0,0,0,0.08);
            display: flex;
            flex-direction: column;
        }
        .highlight-list-item:hover {
            background: rgba(255,255,255,0.09);
            transform: translateY(-1px);
            box-shadow: 0 2px 5px rgba(0,0,0,0.1);
        }
        
        /* 高亮列表项内容 */
        .highlight-list-content {
            margin-bottom: 4px;
            font-size: 13px;
            line-height: 1.3;
            -webkit-line-clamp: 2;
            display: -webkit-box;
            -webkit-box-orient: vertical;
            overflow: hidden;
            text-overflow: ellipsis;
            word-break: break-word;
            position: relative;
            flex: 1;
        }
        
        /* 高亮列表元数据 */
        .highlight-list-meta {
            padding-top: 4px;
            font-size: 11px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-top: 1px solid rgba(255,255,255,0.05);
        }
        
        /* 高亮列表时间显示 */
        .highlight-list-time {
            font-style: italic;
            opacity: 0.8;
            font-size: 11px; /* 稍微调小字体确保完整显示 */
            white-space: nowrap; /* 防止时间换行 */
        }
        
        /* 高亮列表为空提示 */
        .highlight-list p {
            text-align: center;
            color: #aaa;
            font-style: italic;
            background: rgba(255,255,255,0.03);
            border: 1px dashed rgba(255,255,255,0.1);
            padding: 12px;
            font-size: 12px;
            border-radius: 4px;
        }
        
        /* 高亮列表操作区 */
        .highlight-list-actions {
            display: flex;
            gap: 5px;
            align-items: center;
        }
        
        /* 高亮列表操作按钮 */
        .highlight-list-action {
            color: #bbb;
            cursor: pointer;
            transition: all 0.2s;
            font-weight: 500;
            padding: 1px 6px;
            border-radius: 4px;
            font-size: 11px;
        }
        .highlight-list-action:hover {
            color: #fff;
            background-color: #ff5252;
        }
        
        /* ====================
         * 11. 按钮与操作元素
         * ==================== */
        /* 按钮区域固定在底部 */
        #tab-highlights .buttons-row {
            position: sticky;
            bottom: 0;
            background: #333336;
            padding: 0; /* 移除左右内边距 */
            margin: 0; /* 移除外边距 */
            width: 100%; /* 确保全宽 */
            z-index: 2;
            flex-shrink: 0;
            box-shadow: 0 -2px 8px rgba(0,0,0,0.2);
        }
        
        /* 按钮组样式 */
        .buttons-row {
            display: flex;
            gap: 6px;
            margin-top: 10px;
        }
        .buttons-row .sidebar-button {
            flex: 1;
            margin-top: 0;
        }
        
        /* 侧边栏通用按钮样式 */
        .sidebar-button {
            padding: 7px 10px;
            border: none;
            border-radius: 4px;
            background: #ff5252;
            color: white;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.15s ease;
            font-size: 12px;
            margin-top: 5px;
        }
        .sidebar-button:hover {
            background: #e04343;
            transform: translateY(-1px);
        }
        
        /* 按钮变体样式 */
        .sidebar-button.danger {
            background: #ff5252;
        }
        .sidebar-button.danger:hover {
            background: #e04343;
        }
        .sidebar-button.secondary {
            background: rgba(255,255,255,0.08);
            color: #e0e0e0;
            border: 1px solid rgba(255,255,255,0.1);
        }
        .sidebar-button.secondary:hover {
            background: rgba(255,255,255,0.12);
        }
        
        /* 删除按钮样式 */
        .disabled-item-remove {
            color: #ff8080;
            margin-left: 8px;
            cursor: pointer;
            transition: all 0.2s;
            font-weight: 500;
            padding: 1px 6px;
            border-radius: 4px;
            font-size: 11px;
        }
        .disabled-item-remove:hover {
            background-color: #ff5252;
            color: white;
        }
        
        /* ====================
         * 12. 表单控件样式
         * ==================== */
        /* 添加表单样式 */
        .add-disabled-form {
            display: flex;
            margin: 8px 0;
            align-items: stretch;
        }
        
        /* 输入框样式 */
        .add-disabled-input {
            flex: 1;
            padding: 7px 10px;
            border: 1px solid rgba(255,255,255,0.1);
            border-radius: 4px 0 0 4px;
            font-size: 13px;
            color: #e0e0e0;
            background: rgba(255,255,255,0.06);
            margin: 0;
            box-shadow: inset 0 1px 3px rgba(0,0,0,0.1);
            transition: all 0.2s;
            height: auto;
            box-sizing: border-box;
        }
        
        /* 添加按钮样式 */
        .add-disabled-button {
            background: #ff5252;
            color: white;
            border: none;
            border-radius: 0 4px 4px 0;
            cursor: pointer;
            transition: all 0.2s;
            font-weight: 500;
            white-space: nowrap;
            min-width: 56px;
            padding: 0 12px;
            font-size: 13px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-sizing: border-box;
        }
        .add-disabled-button:hover {
            background: #e04343;
        }
        
        /* ====================
         * 13. 禁用列表样式
         * ==================== */
        /* 禁用列表容器 */
        .disabled-list {
            margin-top: 16px;
        }
        
        /* 禁用项样式 */
        .disabled-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 7px 10px;
            border-radius: 4px;
            background: rgba(255,255,255,0.06);
            margin-bottom: 5px;
            border-left: 2px solid rgba(255,255,255,0.2);
        }
        
        /* 禁用项文本 */
        .disabled-item-text {
            font-size: 12px;
            color: #ccc;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            flex: 1;
        }
    `);
    // 初始化
    // 修改init函数,添加延迟高亮恢复
    function init() {
        loadHighlights();

        // 加载固定状态
        sidebarPinned = settings.sidebarPinned || false;

        // 确保初始化时侧边栏状态为关闭
        sidebarOpen = false;

        // 重新检查禁用状态,确保与最新存储同步
        disabledList = GM_getValue('disabled_list', {
            domains: [],
            urls: []
        });
        isHighlightDisabled = disabledList.domains.includes(currentDomain) ||
            disabledList.urls.includes(currentPageUrl);
        createSidebar();
        registerEvents();
        registerMenuCommands();
        addToolbarButton();
        // 如果不禁用高亮,则应用高亮并设置延迟重试
        if (!isHighlightDisabled) {
            // 立即尝试应用高亮
            applyHighlights();
            // 在页面完全加载后再次尝试恢复失败的高亮
            if (document.readyState === 'complete') {
                // 如果已经加载完成,延迟一小段时间再次尝试
                setTimeout(() => retryFailedHighlights(), 1000);
            } else {
                // 否则等待页面加载完成
                window.addEventListener('load', () => {
                    setTimeout(() => retryFailedHighlights(), 500);
                });
            }
            // 再次延迟尝试,确保捕获延迟加载的内容
            setTimeout(() => retryFailedHighlights(), 3000);
        }
    }
    // 添加新函数:重试恢复失败的高亮
    function retryFailedHighlights() {
        console.log('尝试恢复之前失败的高亮...');
        const failedHighlights = highlights.filter(highlight => {
            // 检查此高亮是否已经应用(不存在DOM中则为失败的高亮)
            return !document.querySelector(`.highlight-marked[data-id="${highlight.id}"]`);
        });
        if (failedHighlights.length === 0) {
            console.log('没有找到需要恢复的失败高亮');
            return;
        }
        console.log(`发现 ${failedHighlights.length} 个失败的高亮需要重试恢复`);
        let successCount = 0;
        failedHighlights.forEach(highlight => {
            // 只尝试文本匹配,因为DOM路径可能已经失效
            if (highlight.text && findAndHighlightText(highlight)) {
                console.log(`重试成功恢复高亮: ${highlight.id}`);
                successCount++;
            }
        });
        console.log(`重试恢复结果: 成功=${successCount}, 剩余失败=${failedHighlights.length - successCount}`);
        // 如果还有失败的高亮且侧边栏是打开的,刷新列表确保UI一致性
        if (sidebarOpen) {
            refreshHighlightsList();
        }
    }
    // 加载高亮数据
    function loadHighlights() {
        try {
            const savedHighlights = GM_getValue('highlights', {});
            highlights = savedHighlights[currentPageUrl] || [];
            console.log(`加载了${highlights.length}条高亮记录`);
        } catch (error) {
            console.error('加载高亮数据失败:', error);
            highlights = [];
        }
    }
    // 保存高亮数据
    function saveHighlights() {
        const savedHighlights = GM_getValue('highlights', {});
        savedHighlights[currentPageUrl] = highlights;
        GM_setValue('highlights', savedHighlights);
    }
    // 保存禁用列表
    function saveDisabledList() {
        GM_setValue('disabled_list', disabledList);
    }
    // 创建侧边栏
    function createSidebar() {
        const sidebar = document.createElement('div');
        sidebar.className = 'highlight-sidebar';

        // 设置初始宽度
        const initialWidth = settings.sidebarWidth || 320;
        sidebar.style.setProperty('--sidebar-width', `${initialWidth}px`);
        sidebar.style.width = `${initialWidth}px`;

        // 如果初始状态是关闭的,确保设置正确的隐藏位置
        if (!sidebarOpen) {
            sidebar.style.right = `calc(-1 * ${initialWidth}px)`;
        }

        sidebar.innerHTML = `
            <div class="sidebar-resizer"></div>
            <div class="sidebar-header">
                <div class="sidebar-description" title="双击修改标题">${settings.sidebarDescription || '网页划词高亮工具'}</div>
                <div class="sidebar-controls">
                    <div class="sidebar-btn sidebar-pin ${sidebarPinned ? 'pinned' : ''}" title="固定侧边栏">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <path d="M12 2L12 16"></path>
                            <path d="M5 12H2"></path>
                            <path d="M22 12h-3"></path>
                            <path d="M18 5l-6 7-6-7"></path>
                            <path d="M18 19l-6-7-6 7"></path>
                        </svg>
                    </div>
                    <div class="sidebar-btn sidebar-close" title="关闭">
                        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                            <line x1="18" y1="6" x2="6" y2="18"></line>
                            <line x1="6" y1="6" x2="18" y2="18"></line>
                        </svg>
                    </div>
                </div>
            </div>

            <div class="sidebar-tabs">
                <div class="sidebar-tab active" data-tab="highlights">高亮列表</div>
                <div class="sidebar-tab" data-tab="settings">设置</div>
                <div class="sidebar-tab" data-tab="disabled">禁用管理</div>
            </div>

            <div class="sidebar-content">
                <!-- 高亮列表 -->
                <div class="tab-content active" id="tab-highlights">
                    <div class="highlight-list">
                        ${renderHighlightsList()}
                    </div>
                    <div class="buttons-row">
                        <button class="sidebar-button secondary" id="refresh-highlights">刷新列表</button>
                        <button class="sidebar-button danger" id="clear-all-highlights">清除全部</button>
                    </div>
                </div>

                <!-- 设置选项卡 -->
                <div class="tab-content" id="tab-settings">
                    <div class="sidebar-settings">
                        <label for="triggerMode">触发方式:</label>
                        <select id="triggerMode">
                            <option value="auto" ${settings.triggerMode === 'auto' ? 'selected' : ''}>自动触发(选中后立即显示)</option>
                            <option value="hotkey" ${settings.triggerMode === 'hotkey' ? 'selected' : ''}>快捷键触发 (Ctrl + Alt)</option>
                        </select>

                        <label for="minTextLength">最小触发文本长度:</label>
                        <input type="number" id="minTextLength" min="1" max="50" value="${settings.minTextLength}">

                        <div>
                            <label>高亮颜色:<span class="settings-tip">(点击选择默认颜色)</span></label>
                            <div class="highlight-colors-setting">
                                ${settings.colors.map(color => `
                                    <div class="highlight-menu-color ${color === settings.activeColor ? 'active' : ''}"
                                         style="background-color: ${color};"
                                         data-color="${color}">
                                    </div>
                                `).join('')}
                            </div>
                        </div>

                        <label for="sidebarDescription">侧边栏描述文字:</label>
                        <input type="text" id="sidebarDescription" placeholder="自定义侧边栏描述..." value="${settings.sidebarDescription || '高亮工具'}">

                        <div class="buttons-row">
                            <button class="sidebar-button" id="save-settings">保存设置</button>
                        </div>
                    </div>
                </div>

                <!-- 禁用管理选项卡 -->
                <div class="tab-content" id="tab-disabled">
                    <div>
                        <h3>当前页面</h3>
                        <div class="current-page-status">
                            ${renderCurrentPageStatus()}
                        </div>

                        <h3>禁用域名列表</h3>
                        <div class="disabled-domains-list">
                            ${renderDisabledDomains()}
                        </div>
                        <div class="add-disabled-form">
                            <input type="text" class="add-disabled-input" id="add-domain-input" placeholder="输入域名...">
                            <button class="add-disabled-button" id="add-domain-btn">添加</button>
                        </div>

                        <h3>禁用网址列表</h3>
                        <div class="disabled-urls-list">
                            ${renderDisabledUrls()}
                        </div>
                        <div class="add-disabled-form">
                            <input type="text" class="add-disabled-input" id="add-url-input" placeholder="输入网址...">
                            <button class="add-disabled-button" id="add-url-btn">添加</button>
                        </div>
                    </div>
                </div>
            </div>
        `;

        document.body.appendChild(sidebar);

        // 更新描述文字
        updateSidebarDescription();

        // 绑定侧边栏事件
        bindSidebarEvents(sidebar);

        // 添加标题双击编辑功能
        setupTitleEditing(sidebar);

        // 添加侧边栏宽度调整功能
        setupSidebarResize(sidebar);
    }
    // 设置侧边栏宽度调整功能
    function setupSidebarResize(sidebar) {
        const resizer = sidebar.querySelector('.sidebar-resizer');
        if (!resizer) return;

        // 初始最大/最小宽度设置
        const MIN_WIDTH = 250;
        const MAX_WIDTH = 1600;

        let isDragging = false;
        let initialMouseX = 0;
        let initialWidth = 0;
        let lastEventTime = 0; // 添加事件时间戳用于去重

        // 获取初始宽度(确保有一个有效的起点)
        const currentWidth = parseInt(getComputedStyle(sidebar).width) || settings.sidebarWidth || 320;
        const safeInitialWidth = Math.max(MIN_WIDTH, Math.min(currentWidth, MAX_WIDTH));

        // 立即应用有效的初始宽度
        sidebar.style.width = `${safeInitialWidth}px`;
        sidebar.style.setProperty('--sidebar-width', `${safeInitialWidth}px`);

        // 保存有效宽度到设置
        if (settings.sidebarWidth !== safeInitialWidth) {
            settings.sidebarWidth = safeInitialWidth;
            saveSettings();
        }

        // 处理鼠标按下事件
        function handleMouseDown(e) {
            e.preventDefault();
            e.stopPropagation();

            // 阻止在已经拖动时再次启动拖动
            if (isDragging) return;

            // 记录初始值
            initialMouseX = e.clientX;
            initialWidth = parseInt(getComputedStyle(sidebar).width);

            // 确保初始宽度有效
            if (isNaN(initialWidth) || initialWidth < MIN_WIDTH) {
                initialWidth = MIN_WIDTH;
            } else if (initialWidth > MAX_WIDTH) {
                initialWidth = MAX_WIDTH;
            }

            isDragging = true;

            // 添加拖动类
            resizer.classList.add('dragging');
            document.body.classList.add('sidebar-resizing');

            // 添加临时事件监听
            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
        }

        // 处理触摸开始事件 - 修复:完善触摸事件处理
        function handleTouchStart(e) {
            if (e.touches.length === 1) {
                // 阻止默认事件
                e.preventDefault();
                e.stopPropagation();

                // 使用触摸点代替鼠标位置
                initialMouseX = e.touches[0].clientX;
                initialWidth = parseInt(getComputedStyle(sidebar).width);

                // 确保初始宽度有效
                if (isNaN(initialWidth) || initialWidth < MIN_WIDTH) {
                    initialWidth = MIN_WIDTH;
                } else if (initialWidth > MAX_WIDTH) {
                    initialWidth = MAX_WIDTH;
                }

                isDragging = true;

                // 添加拖动类
                resizer.classList.add('dragging');
                document.body.classList.add('sidebar-resizing');

                // 修复:添加临时事件监听
                document.addEventListener('touchmove', handleTouchMove, { passive: false });
                document.addEventListener('touchend', handleMouseUp);
                document.addEventListener('touchcancel', handleMouseUp);
            }
        }

        // 处理鼠标移动事件 - 修复:修正拖动方向逻辑
        function handleMouseMove(e) {
            if (!isDragging) return;

            e.preventDefault();

            // 计算拖动距离
            // 注意:侧边栏在右侧,向左拖动(正值deltaX)增加宽度,向右拖动(负值deltaX)减少宽度
            const deltaX = e.clientX - initialMouseX;

            // 由于侧边栏在右侧,拖动计算方向相反
            let newWidth = initialWidth - deltaX;

            // 应用限制
            newWidth = Math.max(MIN_WIDTH, Math.min(newWidth, MAX_WIDTH));

            // 修复:增强视觉反馈
            resizer.classList.remove('min-width', 'max-width');
            if (newWidth <= MIN_WIDTH + 5) { // 接近最小值时添加视觉提示
                resizer.classList.add('min-width');
            } else if (newWidth >= MAX_WIDTH - 5) { // 接近最大值时添加视觉提示
                resizer.classList.add('max-width');
            }

            // 应用新宽度 - 同时更新实际width和CSS变量
            sidebar.style.width = `${newWidth}px`;
            sidebar.style.setProperty('--sidebar-width', `${newWidth}px`);
        }

        // 处理触摸移动事件 - 修复:完善触摸事件处理
        function handleTouchMove(e) {
            if (!isDragging || e.touches.length !== 1) return;

            e.preventDefault();

            // 计算拖动距离 - 与鼠标事件保持一致的逻辑
            const deltaX = e.touches[0].clientX - initialMouseX;

            // 由于侧边栏在右侧,拖动计算方向相反
            let newWidth = initialWidth - deltaX;

            // 应用限制
            newWidth = Math.max(MIN_WIDTH, Math.min(newWidth, MAX_WIDTH));

            // 增强视觉反馈
            resizer.classList.remove('min-width', 'max-width');
            if (newWidth <= MIN_WIDTH + 5) {
                resizer.classList.add('min-width');
            } else if (newWidth >= MAX_WIDTH - 5) {
                resizer.classList.add('max-width');
            }

            // 应用新宽度
            sidebar.style.width = `${newWidth}px`;
            sidebar.style.setProperty('--sidebar-width', `${newWidth}px`);
        }

        // 处理鼠标抬起事件 - 修复:添加事件去重机制
        function handleMouseUp(e) {
            // 防止触摸事件后的鼠标事件重复触发
            const now = Date.now();
            if (now - lastEventTime < 100) return;
            lastEventTime = now;

            if (!isDragging) return;

            e.preventDefault();

            // 重要:先读取当前宽度,再重置状态
            let finalWidth = parseInt(getComputedStyle(sidebar).width);

            // 验证最终宽度是否有效
            if (isNaN(finalWidth) || finalWidth < MIN_WIDTH) {
                finalWidth = MIN_WIDTH;
            } else if (finalWidth > MAX_WIDTH) {
                finalWidth = MAX_WIDTH;
            }

            // 重置状态
            isDragging = false;
            resizer.classList.remove('dragging', 'min-width', 'max-width');
            document.body.classList.remove('sidebar-resizing');

            // 移除临时事件监听
            document.removeEventListener('mousemove', handleMouseMove);
            document.removeEventListener('mouseup', handleMouseUp);
            document.removeEventListener('touchmove', handleTouchMove);
            document.removeEventListener('touchend', handleMouseUp);
            document.removeEventListener('touchcancel', handleMouseUp);

            // 确保最终应用的宽度在有效范围内
            const safeWidth = Math.max(MIN_WIDTH, Math.min(finalWidth, MAX_WIDTH));

            // 更新所有与宽度相关的属性,确保一致性
            sidebar.style.width = `${safeWidth}px`;
            sidebar.style.setProperty('--sidebar-width', `${safeWidth}px`);

            // 如果侧边栏当前是关闭状态,确保隐藏位置也更新
            if (!sidebarOpen) {
                sidebar.style.right = `calc(-1 * ${safeWidth}px)`;
            }

            // 保存到设置
            settings.sidebarWidth = safeWidth;
            saveSettings();
        }

        // 绑定事件
        resizer.addEventListener('mousedown', handleMouseDown);
        resizer.addEventListener('touchstart', handleTouchStart, { passive: false });

        // 修复:添加窗口大小变化适配
        window.addEventListener('resize', function () {
            // 如果侧边栏已打开,验证宽度是否合适
            if (sidebarOpen) {
                const maxAllowedWidth = window.innerWidth * 0.8; // 最大不超过窗口宽度的80%
                const currentWidth = parseInt(getComputedStyle(sidebar).width);

                if (currentWidth > maxAllowedWidth) {
                    // 调整为允许的最大宽度
                    const newWidth = Math.min(maxAllowedWidth, MAX_WIDTH);
                    sidebar.style.width = `${newWidth}px`;
                    sidebar.style.setProperty('--sidebar-width', `${newWidth}px`);
                    settings.sidebarWidth = newWidth;
                    saveSettings();
                }
            }
        });
    }
    // 生成高亮列表HTML
    function renderHighlightsList() {
        if (highlights.length === 0) {
            return '<p>当前页面没有高亮内容</p>';
        }

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

        return sortedHighlights.map(highlight => {
            // 限制文本长度,避免过长
            const displayText = highlight.text.length > 100
                ? highlight.text.substring(0, 100) + '...'
                : highlight.text;

            // 格式化时间 - 修改为更精确的格式
            const formattedDate = formatDateTime(highlight.timestamp);

            return `
                <div class="highlight-list-item" data-id="${highlight.id}" style="border-left-color: ${highlight.color}">
                    <div class="highlight-list-content">${sanitizeHTML(displayText)}</div>
                    <div class="highlight-list-meta">
                        <span class="highlight-list-time">${formattedDate}</span>
                        <div class="highlight-list-actions">
                            <span class="highlight-list-action highlight-action-jump" data-id="${highlight.id}">跳转</span>
                            <span class="highlight-list-action highlight-action-remove" data-id="${highlight.id}">删除</span>
                        </div>
                    </div>
                </div>
            `;
        }).join('');
    }

    // 格式化日期时间函数 - YYYY-MM-DD HH:mm:ss
    function formatDateTime(timestamp) {
        const date = new Date(timestamp);
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        const hours = String(date.getHours()).padStart(2, '0');
        const minutes = String(date.getMinutes()).padStart(2, '0');
        const seconds = String(date.getSeconds()).padStart(2, '0');

        return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
    }
    // HTML转义函数
    function sanitizeHTML(text) {
        const element = document.createElement('div');
        element.textContent = text;
        return element.innerHTML;
    }
    // 渲染当前页面状态
    function renderCurrentPageStatus() {
        const isDomainDisabled = disabledList.domains.includes(currentDomain);
        const isUrlDisabled = disabledList.urls.includes(currentPageUrl);

        if (isDomainDisabled) {
            return `
                <div class="disabled-item">
                    <span class="disabled-item-text">此域名 (${currentDomain}) 已禁用高亮</span>
                    <span class="disabled-item-remove" data-type="domain" data-value="${currentDomain}">启用</span>
                </div>
            `;
        } else if (isUrlDisabled) {
            return `
                <div class="disabled-item">
                    <span class="disabled-item-text">此网址已禁用高亮</span>
                    <span class="disabled-item-remove" data-type="url" data-value="${currentPageUrl}">启用</span>
                </div>
            `;
        } else {
            return `
                <div class="buttons-row">
                    <button class="sidebar-button secondary" id="disable-domain">禁用此域名</button>
                    <button class="sidebar-button secondary" id="disable-url">禁用此网址</button>
                </div>
            `;
        }
    }
    // 渲染禁用域名列表
    function renderDisabledDomains() {
        if (disabledList.domains.length === 0) {
            return '<p>没有禁用的域名</p>';
        }

        return disabledList.domains.map(domain => `
            <div class="disabled-item">
                <span class="disabled-item-text">${domain}</span>
                <span class="disabled-item-remove" data-type="domain" data-value="${domain}">删除</span>
            </div>
        `).join('');
    }
    // 渲染禁用网址列表
    function renderDisabledUrls() {
        if (disabledList.urls.length === 0) {
            return '<p>没有禁用的网址</p>';
        }

        return disabledList.urls.map(url => `
            <div class="disabled-item">
                <span class="disabled-item-text">${url}</span>
                <span class="disabled-item-remove" data-type="url" data-value="${url}">删除</span>
            </div>
        `).join('');
    }
    // 绑定侧边栏事件 - 修复标签切换
    function bindSidebarEvents(sidebar) {
        // 关闭侧边栏按钮
        sidebar.querySelector('.sidebar-close').addEventListener('click', () => {
            toggleSidebar(false); // 显式关闭
        });

        // 固定侧边栏按钮
        sidebar.querySelector('.sidebar-pin').addEventListener('click', (e) => {
            const wasPinned = sidebarPinned; // 记录之前的固定状态
            sidebarPinned = !sidebarPinned; // 切换固定状态

            // 更新按钮样式
            e.currentTarget.classList.toggle('pinned', sidebarPinned);

            // 保存固定状态
            settings.sidebarPinned = sidebarPinned;
            saveSettings();

            // 显示提示
            showToast(sidebarPinned ? '侧边栏已固定' : '侧边栏已取消固定', 'info');

            // 如果侧边栏当前是打开状态,处理事件监听器
            if (sidebarOpen) {
                if (wasPinned && !sidebarPinned) {
                    // 从固定变为非固定,添加点击外部关闭事件
                    setTimeout(() => {
                        document.addEventListener('click', handleOutsideClick);
                    }, 10);
                } else if (!wasPinned && sidebarPinned) {
                    // 从非固定变为固定,移除点击外部关闭事件
                    document.removeEventListener('click', handleOutsideClick);
                }
            }
        });

        // 选项卡切换 - 修复选择器和事件处理
        sidebar.querySelectorAll('.sidebar-tab').forEach(tab => {
            tab.addEventListener('click', () => {
                console.log('标签点击:', tab.dataset.tab); // 添加调试日志

                // 移除所有选项卡的激活状态
                sidebar.querySelectorAll('.sidebar-tab').forEach(t => t.classList.remove('active'));
                sidebar.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));

                // 激活当前选项卡
                tab.classList.add('active');

                // 获取对应的内容元素并显示它
                const tabId = `tab-${tab.dataset.tab}`;
                const tabContent = document.getElementById(tabId);

                if (tabContent) {
                    tabContent.classList.add('active');
                    console.log('激活标签内容:', tabId);
                } else {
                    console.error('找不到对应的标签内容元素:', tabId);
                }
            });
        });

        // 高亮列表跳转事件
        sidebar.querySelectorAll('.highlight-action-jump').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const id = e.target.dataset.id;
                jumpToHighlight(id);
                e.stopPropagation();
            });
        });

        // 高亮列表删除事件
        sidebar.querySelectorAll('.highlight-action-remove').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const id = e.target.dataset.id;
                removeHighlightById(id);
                // 刷新高亮列表
                refreshHighlightsList();
                e.stopPropagation();
            });
        });

        // 高亮列表项点击事件(跳转)
        sidebar.querySelectorAll('.highlight-list-item').forEach(item => {
            item.addEventListener('click', () => {
                const id = item.dataset.id;
                jumpToHighlight(id);
            });
        });

        // 保存设置按钮
        sidebar.querySelector('#save-settings').addEventListener('click', () => {
            settings.triggerMode = sidebar.querySelector('#triggerMode').value;
            settings.minTextLength = parseInt(sidebar.querySelector('#minTextLength').value);
            settings.sidebarDescription = sidebar.querySelector('#sidebarDescription').value;
            settings.showFloatingButton = sidebar.querySelector('#showFloatingButton').checked;

            saveSettings();
            updateSidebarDescription();

            // 显示保存成功提示
            showToast('设置已保存');
        });

        // 颜色选择器事件
        const colorElements = sidebar.querySelectorAll('.highlight-colors-setting .highlight-menu-color');
        colorElements.forEach(el => {
            el.addEventListener('click', (e) => {
                settings.activeColor = e.target.dataset.color;
                colorElements.forEach(c => c.classList.remove('active'));
                e.target.classList.add('active');
            });
        });

        // 刷新高亮列表
        sidebar.querySelector('#refresh-highlights').addEventListener('click', refreshHighlightsList);

        // 清除所有高亮
        sidebar.querySelector('#clear-all-highlights').addEventListener('click', () => {
            if (confirm('确定要清除当前页面的所有高亮吗?')) {
                clearAllHighlights();
                refreshHighlightsList();
            }
        });

        // 禁用当前域名
        const disableDomainBtn = sidebar.querySelector('#disable-domain');
        if (disableDomainBtn) {
            disableDomainBtn.addEventListener('click', () => {
                if (confirm(`确定要禁用域名 ${currentDomain} 上的高亮功能吗?`)) {
                    disableDomain(currentDomain);
                }
            });
        }

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

        // 删除禁用项
        sidebar.querySelectorAll('.disabled-item-remove').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const type = e.target.dataset.type;
                const value = e.target.dataset.value;

                if (type === 'domain') {
                    enableDomain(value);
                } else if (type === 'url') {
                    enableUrl(value);
                }
            });
        });

        // 添加禁用域名
        sidebar.querySelector('#add-domain-btn').addEventListener('click', () => {
            const input = sidebar.querySelector('#add-domain-input');
            const domain = input.value.trim();

            if (domain) {
                disableDomain(domain);
                input.value = '';
            }
        });

        // 添加禁用网址
        sidebar.querySelector('#add-url-btn').addEventListener('click', () => {
            const input = sidebar.querySelector('#add-url-input');
            const url = input.value.trim();

            if (url) {
                disableUrl(url);
                input.value = '';
            }
        });
    }
    // 刷新高亮列表
    function refreshHighlightsList() {
        const listContainer = document.querySelector('.highlight-list');
        if (listContainer) {
            listContainer.innerHTML = renderHighlightsList();

            // 重新绑定事件
            const sidebar = document.querySelector('.highlight-sidebar');
            if (sidebar) {
                // 高亮列表跳转事件
                sidebar.querySelectorAll('.highlight-action-jump').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        const id = e.target.dataset.id;
                        jumpToHighlight(id);
                        e.stopPropagation();
                    });
                });

                // 高亮列表删除事件
                sidebar.querySelectorAll('.highlight-action-remove').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        const id = e.target.dataset.id;
                        removeHighlightById(id);
                        // 刷新高亮列表
                        refreshHighlightsList();
                        e.stopPropagation();
                    });
                });

                // 高亮列表项点击事件(跳转)
                sidebar.querySelectorAll('.highlight-list-item').forEach(item => {
                    item.addEventListener('click', () => {
                        const id = item.dataset.id;
                        jumpToHighlight(id);
                    });
                });
            }
        }
    }
    // 保存设置
    function saveSettings() {
        GM_setValue('highlight_settings', settings);
    }
    // 注册菜单命令
    function registerMenuCommands() {
        GM_registerMenuCommand('设置', function () {
            toggleSidebar();
            // 模拟点击设置标签页,切换到设置面板
            setTimeout(() => {
                const settingsTab = document.querySelector('.sidebar-tab[data-tab="settings"]');
                if (settingsTab) settingsTab.click();
            }, 50); // 短暂延迟确保侧边栏已渲染
            return false; // 明确返回false,表示没有异步响应
        });
        GM_registerMenuCommand('清除所有高亮', function () {
            clearAllHighlights();
            return false; // 明确返回false,表示没有异步响应
        });
        GM_registerMenuCommand('显示/隐藏浮动按钮', function () {
            toggleFloatingButton();
            return false; // 明确返回false,表示没有异步响应
        });
    }
    // 清除所有高亮
    function clearAllHighlights() {
        document.querySelectorAll('.highlight-marked').forEach(el => {
            const parent = el.parentNode;
            while (el.firstChild) {
                parent.insertBefore(el.firstChild, el);
            }
            parent.removeChild(el);
        });

        highlights = [];
        saveHighlights();
    }
    // 通过文本内容查找并高亮
    function findAndHighlightText(highlight) {
        // 预处理文本,移除多余空格
        const searchText = highlight.text.trim().replace(/\s+/g, ' ');
        // 获取适合搜索的文本长度
        const searchLength = Math.min(300, searchText.length);
        const searchFragment = searchText.substring(0, searchLength);

        // 文本长度检查 - 修改为更小的阈值,短文本使用精确匹配
        const MIN_LENGTH_FOR_NORMAL_SEARCH = 5;
        if (searchFragment.length < MIN_LENGTH_FOR_NORMAL_SEARCH) {
            console.log(`短文本特殊处理: "${searchFragment}"`);
            // 对于短文本,使用更精确的匹配方式
            return findShortTextExactMatch(searchFragment, highlight);
        }

        console.log(`使用文本片段搜索: "${searchFragment.substring(0, 50)}..."`);

        // 创建TreeWalker来遍历所有文本节点
        const walker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function (node) {
                    // 跳过不可见元素内的文本
                    const parent = node.parentElement;
                    if (!parent) return NodeFilter.FILTER_SKIP;

                    const style = window.getComputedStyle(parent);
                    if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
                        return NodeFilter.FILTER_REJECT;
                    }

                    // 跳过脚本和样式标签内容
                    const parentTag = parent.tagName.toLowerCase();
                    if (parentTag === 'script' || parentTag === 'style' || parentTag === 'noscript') {
                        return NodeFilter.FILTER_REJECT;
                    }

                    // 避免处理已经高亮的内容
                    if (parent.classList && parent.classList.contains('highlight-marked')) {
                        return NodeFilter.FILTER_REJECT;
                    }

                    // 接受有内容的文本节点,降低最小长度要求
                    return node.textContent.trim().length > 0 ?
                        NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
                }
            }
        );

        // 计算文本在页面中出现的次数,并确定应该高亮第几次出现
        const textOccurrenceInfo = findTextOccurrence(searchFragment, highlight.id);
        console.log(`文本"${searchFragment.substring(0, 30)}..."在页面中出现${textOccurrenceInfo.totalOccurrences}次,当前应高亮第${textOccurrenceInfo.skipCount + 1}次出现`);

        // 尝试精确匹配,传入skipCount参数指示跳过前面几个匹配项
        let result = tryExactMatch(walker, searchFragment, highlight, textOccurrenceInfo.skipCount);
        if (result) return true;

        // 如果精确匹配失败,尝试模糊匹配(只用较短的文本片段)
        console.log('精确匹配失败,尝试模糊匹配');
        // 使用前80个字符进行模糊匹配
        const fuzzySearchText = searchFragment.substring(0, Math.min(80, searchFragment.length));
        if (fuzzySearchText.length >= 10) {
            // 重置walker
            walker.currentNode = document.body;
            return tryFuzzyMatch(walker, fuzzySearchText, highlight);
        }
        return false; // 没有找到匹配
    }

    // 查找文本在页面中出现的次数和位置信息
    function findTextOccurrence(searchText, highlightId) {
        // 默认值
        let result = {
            totalOccurrences: 0,
            skipCount: 0
        };

        // 查找页面中已经存在该文本的高亮元素
        const existingHighlights = document.querySelectorAll(`.highlight-marked`);
        let matchingNodes = [];

        // 第一步:计算总共出现次数
        const textFinder = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function (node) {
                    // 使用与上面相同的过滤逻辑
                    const parent = node.parentElement;
                    if (!parent) return NodeFilter.FILTER_SKIP;

                    const style = window.getComputedStyle(parent);
                    if (style.display === 'none' || style.visibility === 'hidden') {
                        return NodeFilter.FILTER_REJECT;
                    }

                    const parentTag = parent.tagName.toLowerCase();
                    if (parentTag === 'script' || parentTag === 'style') {
                        return NodeFilter.FILTER_REJECT;
                    }

                    return NodeFilter.FILTER_ACCEPT;
                }
            }
        );

        // 遍历所有文本节点寻找匹配的文本
        let textNode;
        while (textNode = textFinder.nextNode()) {
            const nodeText = textNode.textContent;
            let startIndex = 0;
            let index;

            // 在当前节点中查找所有匹配项
            while ((index = nodeText.indexOf(searchText, startIndex)) !== -1) {
                result.totalOccurrences++;
                matchingNodes.push({
                    node: textNode,
                    index: index
                });
                startIndex = index + 1; // 继续查找下一个匹配位置
            }
        }

        // 第二步:确定应该跳过的数量
        // 查看已有的同文本高亮,确定这次应该高亮第几次出现的文本
        for (let i = 0; i < existingHighlights.length; i++) {
            const highlightElement = existingHighlights[i];
            // 排除当前正在处理的高亮元素
            if (highlightElement.dataset.id === highlightId) {
                continue;
            }
            // 检查文本是否匹配
            if (highlightElement.textContent === searchText) {
                result.skipCount++;
            }
        }

        return result;
    }

    // 添加新函数: 短文本精确匹配
    function findShortTextExactMatch(searchText, highlight) {
        // 为短文本创建一个专用的TreeWalker
        const walker = document.createTreeWalker(
            document.body,
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function (node) {
                    // 基本过滤与主函数相同
                    const parent = node.parentElement;
                    if (!parent) return NodeFilter.FILTER_SKIP;

                    const style = window.getComputedStyle(parent);
                    if (style.display === 'none' || style.visibility === 'hidden') {
                        return NodeFilter.FILTER_REJECT;
                    }

                    // 添加这一行定义parentTag变量
                    const parentTag = parent.tagName.toLowerCase();

                    if (parentTag === 'script' || parentTag === 'style') {
                        return NodeFilter.FILTER_REJECT;
                    }

                    if (parent.classList && parent.classList.contains('highlight-marked')) {
                        return NodeFilter.FILTER_REJECT;
                    }

                    // 对短文本,我们需要精确匹配
                    if (node.textContent.includes(searchText)) {
                        return NodeFilter.FILTER_ACCEPT;
                    }

                    return NodeFilter.FILTER_SKIP;
                }
            }
        );

        // 遍历找到包含该短文本的节点
        let textNode;
        while (textNode = walker.nextNode()) {
            const nodeText = textNode.textContent;
            const startIndex = nodeText.indexOf(searchText);

            if (startIndex >= 0) {
                try {
                    // 创建范围并应用高亮
                    const range = document.createRange();
                    range.setStart(textNode, startIndex);
                    range.setEnd(textNode, startIndex + searchText.length);

                    if (applyHighlightToRange(range, highlight, true)) {
                        console.log(`短文本精确匹配成功: "${searchText}"`);
                        return true;
                    }
                } catch (e) {
                    console.log('短文本匹配失败:', e);
                    continue;
                }
            }
        }

        console.log(`短文本无法找到匹配: "${searchText}"`);
        return false;
    }
    // 尝试精确匹配
    function tryExactMatch(walker, searchText, highlight, skipCount = 0) {
        let textNode;
        let matchCount = 0; // 用于计数匹配到的次数

        while (textNode = walker.nextNode()) {
            // 获取节点的完整文本内容
            const nodeText = textNode.textContent;
            let startSearchPos = 0;
            let currentIndex;

            // 在当前节点内查找所有匹配项
            while ((currentIndex = nodeText.indexOf(searchText, startSearchPos)) >= 0) {
                // 找到一个匹配项,检查是否应该跳过
                if (matchCount < skipCount) {
                    // 还需要跳过这个匹配项
                    matchCount++;
                    startSearchPos = currentIndex + 1; // 从下一个位置继续搜索
                    continue;
                }

                try {
                    // 找到了需要高亮的匹配项,创建一个范围
                    const range = document.createRange();
                    range.setStart(textNode, currentIndex);
                    range.setEnd(textNode, currentIndex + searchText.length);
                    // 应用高亮
                    if (applyHighlightToRange(range, highlight, true)) {
                        console.log(`精确匹配成功(第${matchCount + 1}次出现): "${searchText.substring(0, 30)}..."`);
                        return true;
                    }
                } catch (e) {
                    console.log('精确匹配失败:', e);
                }

                // 无论是否成功,都移动到下一个位置继续搜索
                matchCount++;
                startSearchPos = currentIndex + 1;
            }
        }
        return false;
    }
    // 尝试模糊匹配
    function tryFuzzyMatch(walker, searchText, highlight) {
        let textNode;
        while (textNode = walker.nextNode()) {
            // 获取节点的完整文本内容并规范化
            const nodeText = textNode.textContent.trim().replace(/\s+/g, ' ');
            // 检查是否包含搜索文本的大部分内容(允许少量差异)
            if (fuzzyContains(nodeText, searchText)) {
                try {
                    // 找到最佳匹配位置
                    const bestMatchIndex = getBestMatchPosition(nodeText, searchText);
                    if (bestMatchIndex >= 0) {
                        // 创建一个范围,使用模糊匹配的最佳位置
                        const range = document.createRange();
                        const endPos = Math.min(bestMatchIndex + searchText.length, nodeText.length);
                        range.setStart(textNode, bestMatchIndex);
                        range.setEnd(textNode, endPos);
                        // 应用高亮
                        if (applyHighlightToRange(range, highlight, true)) {
                            console.log(`模糊匹配成功: "${searchText.substring(0, 30)}..."`);
                            return true;
                        }
                    }
                } catch (e) {
                    console.log('模糊匹配失败:', e);
                    continue; // 继续尝试其他匹配项
                }
            }
        }
        return false;
    }
    // 检查文本是否模糊包含搜索文本
    function fuzzyContains(text, search) {
        // 简单实现:检查是否包含80%以上的搜索文本
        const minLength = Math.floor(search.length * 0.8);
        let matchedChars = 0;
        // 在text中查找search的字符,允许少量不连续
        let lastIndex = -1;
        for (let i = 0; i < search.length; i++) {
            const char = search[i];
            const index = text.indexOf(char, lastIndex + 1);
            if (index > -1) {
                matchedChars++;
                lastIndex = index;
            }
        }
        return matchedChars >= minLength;
    }
    // 找出最佳匹配位置
    function getBestMatchPosition(text, search) {
        // 简单实现:寻找最长连续匹配子串的起始位置
        let bestLength = 0;
        let bestIndex = -1;
        for (let i = 0; i <= text.length - search.length; i++) {
            let matchLength = 0;
            for (let j = 0; j < search.length; j++) {
                if (i + j < text.length && text[i + j] === search[j]) {
                    matchLength++;
                } else {
                    break;
                }
            }
            if (matchLength > bestLength) {
                bestLength = matchLength;
                bestIndex = i;
            }
        }
        // 要求至少匹配50%的字符才返回位置
        return bestLength >= search.length * 0.5 ? bestIndex : -1;
    }
    // 将高亮应用到指定范围(提取通用逻辑)
    function applyHighlightToRange(range, highlight, isRecovered = false) {
        try {
            const span = document.createElement('span');
            span.className = 'highlight-marked';
            if (isRecovered) {
                span.classList.add('highlight-recovered');
            }
            span.style.backgroundColor = highlight.color;
            span.dataset.id = highlight.id;
            try {
                range.surroundContents(span);
                span.addEventListener('click', (e) => {
                    e.stopPropagation();
                    showHighlightContextMenu(e, highlight.id);
                });
                return true;
            } catch (e) {
                console.log('无法直接应用高亮,使用备用方法:', e);
                try {
                    // 尝试替代方法
                    const fragment = range.extractContents();
                    span.appendChild(fragment);
                    range.insertNode(span);
                    span.addEventListener('click', (e) => {
                        e.stopPropagation();
                        showHighlightContextMenu(e, highlight.id);
                    });
                    return true;
                } catch (innerErr) {
                    console.error('所有方法都无法应用高亮:', innerErr);
                    return false;
                }
            }
        } catch (e) {
            console.error('应用高亮到范围失败:', e);
            return false;
        }
    }
    // 改进从路径构建Range对象的函数 - 添加更多错误处理
    function constructRangeFromPath(path) {
        if (!path || !path.startContainer || !path.endContainer) {
            console.log('路径信息不完整');
            return null;
        }
        try {
            const range = document.createRange();
            const startContainer = getNodeByPath(path.startContainer);
            const endContainer = getNodeByPath(path.endContainer);
            if (!startContainer || !endContainer) {
                console.log('无法找到开始或结束节点');
                return null;
            }
            range.setStart(startContainer, path.startOffset);
            range.setEnd(endContainer, path.endOffset);
            return range;
        } catch (e) {
            console.log('构建Range时出错:', e);
            return null;
        }
    }
    // 改进根据路径获取节点的函数 - 增加健壮性
    function getNodeByPath(path) {
        if (!path || !Array.isArray(path) || path.length === 0) {
            return null;
        }
        let node = document.body;
        try {
            for (let i = 0; i < path.length; i++) {
                const index = path[i];
                // 检查子节点索引是否有效
                if (!node.childNodes || node.childNodes.length <= index) {
                    return null;
                }
                node = node.childNodes[index];
            }
            return node;
        } catch (e) {
            console.error('根据路径获取节点失败:', e);
            return null;
        }
    }
    // 获取节点路径
    function getNodePath(node, root = document.body) {
        const path = [];
        let current = node;
        while (current !== root) {
            const parent = current.parentNode;
            if (!parent) break;

            const index = Array.prototype.indexOf.call(parent.childNodes, current);
            path.unshift(index);
            current = parent;
        }
        return path;
    }
    // 创建高亮菜单 - 微信读书风格
    function createHighlightMenu(isNewHighlight = true) {
        const menu = document.createElement('div');
        menu.className = 'highlight-menu';
        menu.innerHTML = `
            <div class="highlight-menu-colors">
                ${settings.colors.map(color => `
                    <div class="highlight-menu-color ${!isNewHighlight && color === settings.activeColor ? 'active' : ''}"
                         style="background-color: ${color};"
                         data-color="${color}">
                    </div>
                `).join('')}
            </div>
        `;
        // 添加属性用于跟踪当前高亮ID
        menu.dataset.currentHighlightId = '';
        document.body.appendChild(menu);
        return menu;
    }
    // 移除高亮菜单 - 平滑淡出
    function removeHighlightMenu() {
        // 移除可能存在的全局点击事件处理器
        document.removeEventListener('click', window.currentMenuCloseHandler);
        window.currentMenuCloseHandler = null;
        const menu = document.querySelector('.highlight-menu');
        if (menu) {
            // 平滑移除:触发淡出动画,再移除元素
            menu.classList.remove('show');
            // 等待动画完成再移除DOM元素
            setTimeout(() => {
                if (menu.parentNode) menu.remove();
            }, 200);
        }
    }
    // 显示高亮菜单 - 修改动画逻辑为直接淡入
    function showHighlightMenu(e) {
        const selection = window.getSelection();
        const selectedText = selection.toString().trim();
        if (!selectedText || selectedText.length < settings.minTextLength) {
            return;
        }
        // 如果菜单正在动画中,不再触发新的显示
        if (menuAnimating) {
            return;
        }
        // 设置动画状态为true
        menuAnimating = true;
        // 设置忽略下一次点击,防止双击时第二次点击关闭菜单
        ignoreNextClick = true;

        // 保存当前选择范围
        const savedRange = selection.rangeCount > 0 ? selection.getRangeAt(0).cloneRange() : null;
        // 移除现有菜单
        removeHighlightMenu();
        // 新选中文本时不应该显示已选中颜色图标
        const menu = createHighlightMenu(true);
        // 获取选择范围的客户端矩形集合 - 这比getBoundingClientRect更精确
        const range = selection.getRangeAt(0);
        const rects = range.getClientRects();
        if (rects.length === 0) {
            menuAnimating = 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`;
            // 清除任何先前的transform
            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('arrow-top');
            } else {
                menu.classList.remove('arrow-top');
            }
            // 添加显示类触发淡入动画
            requestAnimationFrame(() => {
                menu.classList.add('show');

                // 动画完成后重置状态
                setTimeout(() => {
                    menuAnimating = false;
                }, 250);

                setTimeout(() => {
                    ignoreNextClick = false;
                }, 300);
            });
        }, 0);
        // 绑定颜色选择事件
        menu.querySelectorAll('.highlight-menu-color').forEach(el => {
            el.addEventListener('click', (e) => {
                // 如果正在处理颜色点击,忽略此次点击
                if (isProcessingColorClick) {
                    e.stopPropagation();
                    return;
                }
                // 设置处理状态为true
                isProcessingColorClick = true;
                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('.highlight-menu-color').forEach(colorEl => {
                            colorEl.classList.remove('active');
                        });
                    } else {
                        // 如果是新选择的文本,只清除选择而不关闭菜单
                        window.getSelection().removeAllRanges();
                        // 重置所有颜色状态为非激活
                        menu.querySelectorAll('.highlight-menu-color').forEach(colorEl => {
                            colorEl.classList.remove('active');
                        });
                    }
                } else {
                    // 点击非激活状态的颜色块 - 应用高亮颜色
                    settings.activeColor = color;
                    saveSettings();

                    if (currentHighlightId) {
                        // 如果已有高亮ID,直接更新颜色
                        changeHighlightColor(currentHighlightId, color);
                    } else {
                        // 检查选择是否丢失并恢复
                        const selection = window.getSelection();
                        if (selection.toString().trim() === '' && savedRange) {
                            selection.removeAllRanges();
                            selection.addRange(savedRange);
                        }
                        // 应用高亮
                        const newHighlightId = highlightSelection(color);
                        // 保存高亮ID以便后续更新
                        if (newHighlightId) {
                            menu.dataset.currentHighlightId = newHighlightId;
                        }
                    }
                    // 更新菜单中的活动颜色
                    menu.querySelectorAll('.highlight-menu-color').forEach(colorEl => {
                        colorEl.classList.toggle('active', colorEl.dataset.color === color);
                    });
                }

                // 在处理完成后重置状态
                setTimeout(() => {
                    isProcessingColorClick = false;
                }, 50);

                // 阻止事件冒泡,防止触发document的click事件
                e.stopPropagation();
            });
        });
        // 存储关闭函数的引用以便后续移除
        const closeMenu = function (e) {
            // 如果标记为忽略点击,则不关闭菜单
            if (ignoreNextClick) {
                return;
            }
            if (!menu.contains(e.target)) {
                removeHighlightMenu();
            }
        };
        // 全局存储当前菜单的关闭处理器以确保能正确移除
        window.currentMenuCloseHandler = closeMenu;

        // 修改:先添加事件监听器,再重置ignoreNextClick
        setTimeout(() => {
            document.addEventListener('click', window.currentMenuCloseHandler);

            // 确保事件监听器添加后再重置忽略标志
            setTimeout(() => {
                ignoreNextClick = false;
            }, 50);
        }, 300);
    }
    // 显示高亮上下文菜单 - 应用相同的动画修改
    function showHighlightContextMenu(e, id) {
        // 如果菜单正在动画中,不再触发新的显示
        if (menuAnimating) {
            return;
        }
        // 设置动画状态为true
        menuAnimating = true;
        // 设置忽略下一次点击,防止误触关闭菜单
        ignoreNextClick = true;
        // 移除现有菜单
        removeHighlightMenu();
        // 获取高亮元素的位置
        const highlightElements = document.querySelectorAll(`.highlight-marked[data-id="${id}"]`);
        if (!highlightElements.length) {
            menuAnimating = false;
            return;
        }
        // 获取触发事件的高亮元素或第一个高亮元素
        let targetElement;
        if (e && e.target && e.target.classList.contains('highlight-marked')) {
            targetElement = e.target; // 使用触发事件的元素
        } else {
            targetElement = highlightElements[0]; // 使用第一个高亮元素
        }
        const rect = targetElement.getBoundingClientRect();
        // 对已存在高亮的菜单,应该显示已选中的颜色
        const menu = createHighlightMenu(false);
        menu.dataset.currentHighlightId = id;
        // 找到当前高亮的颜色并更新菜单
        const highlight = highlights.find(h => h.id === id);
        if (highlight) {
            menu.querySelectorAll('.highlight-menu-color').forEach(colorEl => {
                colorEl.classList.toggle('active', colorEl.dataset.color === highlight.color);
            });
        }
        // 预估菜单高度
        const menuHeight = 50;
        // 计算初始位置 - 放在高亮元素上方中心
        let initialTop = window.scrollY + rect.top - menuHeight - 8;
        let showAbove = true;
        // 如果上方空间不足,放在下方
        if (rect.top < menuHeight + 10) {
            initialTop = window.scrollY + rect.bottom + 8;
            showAbove = false;
        }
        // 设置菜单初始位置
        menu.style.top = `${initialTop}px`;
        // 调整菜单确保在可视区域内
        setTimeout(() => {
            const menuWidth = menu.offsetWidth;
            // 计算高亮元素中心位置
            const targetCenterX = rect.left + (rect.width / 2);
            // 确保菜单在视口范围内
            let menuLeft;
            if (targetCenterX - (menuWidth / 2) < 5) {
                menuLeft = 5; // 贴近左边界
            } else if (targetCenterX + (menuWidth / 2) > window.innerWidth - 5) {
                menuLeft = window.innerWidth - menuWidth - 5; // 贴近右边界
            } else {
                menuLeft = targetCenterX - (menuWidth / 2); // 居中对齐
            }
            // 设置菜单位置
            menu.style.left = `${menuLeft}px`;
            // 清除任何先前的transform
            menu.style.transform = 'none';
            // 计算并设置箭头位置 - 箭头应该指向高亮元素中心
            const arrowLeft = targetCenterX - 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('arrow-top');
            } else {
                menu.classList.remove('arrow-top');
            }
            // 添加显示类触发淡入动画
            requestAnimationFrame(() => {
                menu.classList.add('show');
                // 动画完成后重置状态
                setTimeout(() => {
                    menuAnimating = false;
                }, 250);
                setTimeout(() => {
                    ignoreNextClick = false;
                }, 300);
            });
        }, 0);
        // 绑定颜色选择事件
        menu.querySelectorAll('.highlight-menu-color').forEach(el => {
            el.addEventListener('click', (e) => {
                // 如果正在处理颜色点击,忽略此次点击
                if (isProcessingColorClick) {
                    e.stopPropagation();
                    return;
                }

                // 设置处理状态为true
                isProcessingColorClick = true;

                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('.highlight-menu-color').forEach(colorEl => {
                            colorEl.classList.remove('active');
                        });
                    }
                } else {
                    // 点击非激活状态的颜色块 - 更新高亮颜色
                    changeHighlightColor(currentHighlightId, color);
                    // 更新菜单中的活动颜色
                    menu.querySelectorAll('.highlight-menu-color').forEach(colorEl => {
                        colorEl.classList.toggle('active', colorEl.dataset.color === color);
                    });
                }

                // 在处理完成后重置状态
                setTimeout(() => {
                    isProcessingColorClick = false;
                }, 50);
                // 阻止事件冒泡,防止触发document的click事件
                e.stopPropagation();
            });
        });
        // 存储关闭函数的引用以便后续移除
        const closeMenu = function (e) {
            // 如果标记为忽略点击,则不关闭菜单
            if (ignoreNextClick) {
                return;
            }
            if (!menu.contains(e.target)) {
                removeHighlightMenu();
            }
        };
        // 全局存储当前菜单的关闭处理器以确保能正确移除
        window.currentMenuCloseHandler = closeMenu;

        // 修改:先添加事件监听器,再重置ignoreNextClick
        setTimeout(() => {
            document.addEventListener('click', window.currentMenuCloseHandler);

            // 确保事件监听器添加后再重置忽略标志
            setTimeout(() => {
                ignoreNextClick = false;
            }, 50);
        }, 300);
    }
    // 高亮选中文本
    function highlightSelection(color) {
        const selection = window.getSelection();
        if (!selection.toString().trim()) {
            console.log('尝试高亮时没有选择文本');
            return null;
        }
        try {
            // 检查选择是否仍然有范围
            if (selection.rangeCount === 0) {
                console.log('选择中没有范围 - 选择可能已经丢失');
                return null;
            }
            const range = selection.getRangeAt(0);
            const selectedText = selection.toString().trim();
            console.log('正在高亮文本:', selectedText);

            // 移除原有的文本去重逻辑,统一创建新的高亮记录
            // 生成唯一ID
            const id = 'highlight-' + Date.now();

            // 创建路径信息
            const pathInfo = {
                startContainer: getNodePath(range.startContainer),
                startOffset: range.startOffset,
                endContainer: getNodePath(range.endContainer),
                endOffset: range.endOffset
            };

            // 检查范围内是否包含已有的高亮元素
            const containsHighlight = containsHighlightElement(range);

            // 使用安全的高亮处理方法
            if (containsHighlight) {
                // 使用增强的高亮方法处理复杂选择
                safelyHighlightComplexRange(range, id, color);
            } else {
                // 创建高亮元素
                const span = document.createElement('span');
                span.className = 'highlight-marked';
                span.style.backgroundColor = color;
                span.dataset.id = id;
                try {
                    range.surroundContents(span);
                    console.log('成功使用surroundContents应用高亮');
                } catch (e) {
                    console.log('无法直接高亮,尝试替代方法:', e);
                    safelyHighlightComplexRange(range, id, color);
                }
            }

            // 添加点击事件监听器
            const highlightElements = document.querySelectorAll(`[data-id="${id}"]`);
            highlightElements.forEach(el => {
                el.addEventListener('click', (e) => {
                    e.stopPropagation();
                    showHighlightContextMenu(e, id);
                });
            });

            // 保存高亮信息
            highlights.push({
                id: id,
                text: selectedText,
                color: color,
                timestamp: Date.now(),
                path: pathInfo,
                isComplex: containsHighlight
            });

            saveHighlights();
            console.log('新高亮已保存,ID:', id);

            // 检查侧边栏是否打开,如果打开则刷新高亮列表
            if (sidebarOpen) {
                refreshHighlightsList();
            }

            return id;
        } catch (e) {
            console.error('无法高亮:', e);
            alert('无法高亮选定的文本。尝试选择较短的文本段落或避免跨多个元素选择。');
            return null;
        }
    }
    // 检查范围内是否包含已有的高亮元素
    function containsHighlightElement(range) {
        const nodes = getNodesInRange(range);
        return nodes.some(node =>
            node.nodeType === Node.ELEMENT_NODE &&
            node.classList &&
            node.classList.contains('highlight-marked')
        );
    }
    // 修改高亮颜色 - 更新为支持多元素复杂高亮
    function changeHighlightColor(id, color) {
        // 查找所有具有相同ID的高亮元素(适用于复杂情况)
        const highlightElements = document.querySelectorAll(`.highlight-marked[data-id="${id}"]`);
        if (highlightElements.length > 0) {
            highlightElements.forEach(el => {
                el.style.backgroundColor = color;
            });
            // 更新数据
            const index = highlights.findIndex(h => h.id === id);
            if (index !== -1) {
                // 更新颜色和时间戳
                highlights[index].color = color;
                highlights[index].timestamp = Date.now(); // 更新时间戳,使其在列表中保持靠前
                saveHighlights();
                // 尝试刷新侧边栏列表,保持UI同步
                refreshHighlightsList();
            }
        }
    }
    // 获取Range内的所有节点
    function getNodesInRange(range) {
        const nodes = [];
        const iterator = document.createNodeIterator(
            range.commonAncestorContainer,
            NodeFilter.SHOW_ALL
        );
        let node;
        while (node = iterator.nextNode()) {
            if (range.intersectsNode(node)) {
                nodes.push(node);
            }
        }
        return nodes;
    }
    // 注册事件
    function registerEvents() {
        // 监听鼠标抬起事件
        document.addEventListener('mouseup', function (e) {
            // 如果页面被禁用,不执行任何高亮操作
            if (isHighlightDisabled) {
                return;
            }
            // 防止点击菜单时触发
            if (e.target.closest('.highlight-menu') || e.target.closest('.highlight-settings')) {
                return;
            }
            // 检查是否在侧边栏内选择文本
            if (e.target.closest('.highlight-sidebar')) {
                return;
            }
            // 检测是否为双击
            const isDoubleClick = (e.detail === 2);
            // 加强防抖处理,防止双击触发两次
            clearTimeout(menuDisplayTimer);
            // 如果菜单正在动画中,直接跳过
            if (menuAnimating) {
                return;
            }
            // 检查距离上次显示菜单的时间是否大于300ms,防止双击显示两次
            const now = Date.now();
            if (now - lastMenuDisplayTime < 300) { // 增加时间阈值
                return;
            }
            // 调整延迟时间根据是否为双击
            // 双击情况下增加更多延迟,以确保选择完成
            const delay = isDoubleClick ? 30 : 10;

            menuDisplayTimer = setTimeout(() => {
                if (settings.triggerMode === 'auto') {
                    showHighlightMenu(e);
                    lastMenuDisplayTime = Date.now(); // 记录本次显示时间
                }
                // 注意:这里不再检查Shift键,因为我们改用Ctrl+Alt触发
            }, delay);
        });

        // 新增:监听键盘事件,检测Ctrl+Alt组合键
        document.addEventListener('keydown', function (e) {
            // 如果页面被禁用,不执行任何高亮操作
            if (isHighlightDisabled) {
                return;
            }

            // 检查是否为Ctrl+Alt组合键,且triggerMode为hotkey
            if (e.ctrlKey && e.altKey && !e.shiftKey && !e.metaKey && settings.triggerMode === 'hotkey') {
                const selection = window.getSelection();
                const selectedText = selection.toString().trim();

                if (selectedText && selectedText.length >= settings.minTextLength) {
                    // 直接应用高亮,使用当前活动颜色
                    highlightSelection(settings.activeColor);
                    e.preventDefault(); // 阻止默认行为
                }
            }
        });
    }
    // 侧边栏开关功能
    function toggleSidebar(forcedState) {
        console.log("切换侧边栏, 强制状态:", forcedState);
        const sidebar = document.querySelector('.highlight-sidebar');
        console.log("侧边栏元素存在:", sidebar ? "是" : "否");
        if (!sidebar) {
            console.warn("找不到侧边栏元素,尝试重新创建");
            createSidebar();

            // 再次尝试获取侧边栏
            const newSidebar = document.querySelector('.highlight-sidebar');
            if (!newSidebar) {
                console.error("侧边栏创建失败!");
                return;
            }
            // 如果创建成功,强制设置为打开状态
            sidebarOpen = false; // 确保初始状态为关闭
            forcedState = true; // 然后强制打开
        }
        // 记录之前的状态,用于检测是否从关闭变为打开
        const wasOpen = sidebarOpen;
        // 如果提供了强制状态,使用它;否则切换当前状态
        if (forcedState !== undefined) {
            sidebarOpen = forcedState;
        } else {
            sidebarOpen = !sidebarOpen;
        }
        console.log("侧边栏状态:", sidebarOpen ? "打开" : "关闭");
        if (sidebarOpen) {
            // 确保CSS变量设置正确
            const width = settings.sidebarWidth || 320;
            sidebar.style.setProperty('--sidebar-width', `${width}px`);
            sidebar.style.width = `${width}px`;
            // 强制浏览器重绘,确保过渡效果正常
            sidebar.offsetHeight; // 触发重绘
            sidebar.classList.add('open');
            // 明确设置right为0,确保显示
            sidebar.style.right = '0';
            // 从关闭状态变为打开状态时,刷新高亮列表
            if (!wasOpen) {
                refreshHighlightsList();
            }
            // 如果侧边栏没有被固定,添加点击外部关闭事件
            if (!sidebarPinned) {
                setTimeout(() => {
                    document.addEventListener('click', handleOutsideClick);
                }, 10);
            }
        } else {
            sidebar.classList.remove('open');
            // 确保关闭时隐藏位置与当前宽度匹配
            const currentWidth = parseInt(getComputedStyle(sidebar).getPropertyValue('--sidebar-width')) || settings.sidebarWidth || 320;
            sidebar.style.setProperty('--sidebar-width', `${currentWidth}px`);
            sidebar.style.right = `calc(-1 * ${currentWidth}px)`;
            // 移除点击外部关闭事件
            document.removeEventListener('click', handleOutsideClick);
        }
    }
    // 处理点击侧边栏外部事件
    function handleOutsideClick(e) {
        const sidebar = document.querySelector('.highlight-sidebar');
        if (!sidebar) return;
        // 如果侧边栏已固定,不关闭
        if (sidebarPinned) {
            document.removeEventListener('click', handleOutsideClick);
            return;
        }
        // 如果点击的是侧边栏内部或高亮工具按钮,不关闭
        if (sidebar.contains(e.target) || e.target.closest('.highlight-toolbar')) {
            return;
        }
        // 关闭侧边栏
        toggleSidebar(false);
    }
    // 跳转到高亮位置
    function jumpToHighlight(id) {
        const highlightElement = document.querySelector(`.highlight-marked[data-id="${id}"]`);
        if (highlightElement) {
            // 计算元素相对于视口顶部的距离
            const elementTop = highlightElement.getBoundingClientRect().top + window.scrollY;
            // 添加一个临时闪烁类来突出显示高亮内容
            highlightElement.classList.add('highlight-flash');
            // 设置一个偏移量,使元素不会紧贴窗口顶部
            const offset = window.innerHeight * 0.2;
            // 平滑滚动到元素位置
            window.scrollTo({
                top: elementTop - offset,
                behavior: 'smooth'
            });
            // 滚动后移除闪烁效果
            setTimeout(() => {
                highlightElement.classList.remove('highlight-flash');
            }, 1500);
        }
    }
    // 禁用域名
    function disableDomain(domain) {
        // 防止重复添加
        if (!disabledList.domains.includes(domain)) {
            disabledList.domains.push(domain);
            saveDisabledList();
            // 如果是当前域名,应用禁用效果
            if (domain === currentDomain) {
                isHighlightDisabled = true;
                clearAllHighlights();
                // 更新页面状态提示
                showToast(`已禁用域名 ${domain} 的高亮功能`);
            } else {
                showToast(`已添加到禁用域名列表`);
            }
            // 刷新禁用管理选项卡
            refreshDisabledList();
        }
    }
    // 启用域名
    function enableDomain(domain) {
        disabledList.domains = disabledList.domains.filter(d => d !== domain);
        saveDisabledList();
        // 如果是当前域名,更新状态
        if (domain === currentDomain) {
            // 需要检查URL是否也被禁用
            isHighlightDisabled = disabledList.urls.includes(currentPageUrl);
            if (!isHighlightDisabled) {
                loadHighlights();
                applyHighlights();
            }
            showToast(`已启用域名 ${domain} 的高亮功能`);
        } else {
            showToast(`已从禁用域名列表中移除`);
        }
        // 刷新禁用管理选项卡
        refreshDisabledList();
    }
    // 禁用URL
    function disableUrl(url) {
        // 防止重复添加
        if (!disabledList.urls.includes(url)) {
            disabledList.urls.push(url);
            saveDisabledList();
            // 如果是当前URL,应用禁用效果
            if (url === currentPageUrl) {
                isHighlightDisabled = true;
                clearAllHighlights();
                showToast(`已禁用当前网址的高亮功能`);
            } else {
                showToast(`已添加到禁用网址列表`);
            }
            // 刷新禁用管理选项卡
            refreshDisabledList();
        }
    }
    // 启用URL
    function enableUrl(url) {
        disabledList.urls = disabledList.urls.filter(u => u !== url);
        saveDisabledList();
        // 如果是当前URL,更新状态
        if (url === currentPageUrl) {
            // 需要检查域名是否也被禁用
            isHighlightDisabled = disabledList.domains.includes(currentDomain);
            if (!isHighlightDisabled) {
                loadHighlights();
                applyHighlights();
            }
            showToast(`已启用当前网址的高亮功能`);
        } else {
            showToast(`已从禁用网址列表中移除`);
        }
        // 刷新禁用管理选项卡
        refreshDisabledList();
    }
    // 刷新禁用列表UI
    function refreshDisabledList() {
        // 更新当前页面状态
        const currentPageStatus = document.querySelector('.current-page-status');
        if (currentPageStatus) {
            currentPageStatus.innerHTML = renderCurrentPageStatus();
        }
        // 更新禁用域名列表
        const domainsListContainer = document.querySelector('.disabled-domains-list');
        if (domainsListContainer) {
            domainsListContainer.innerHTML = renderDisabledDomains();
        }
        // 更新禁用网址列表
        const urlsListContainer = document.querySelector('.disabled-urls-list');
        if (urlsListContainer) {
            urlsListContainer.innerHTML = renderDisabledUrls();
        }
        // 重新绑定事件
        bindDisabledListEvents();
    }
    // 绑定禁用列表事件
    function bindDisabledListEvents() {
        // 获取侧边栏
        const sidebar = document.querySelector('.highlight-sidebar');
        if (!sidebar) return;
        // 当前页面启用/禁用按钮
        const disableDomainBtn = sidebar.querySelector('#disable-domain');
        if (disableDomainBtn) {
            disableDomainBtn.addEventListener('click', () => {
                if (confirm(`确定要禁用域名 ${currentDomain} 上的高亮功能吗?`)) {
                    disableDomain(currentDomain);
                }
            });
        }
        const disableUrlBtn = sidebar.querySelector('#disable-url');
        if (disableUrlBtn) {
            disableUrlBtn.addEventListener('click', () => {
                if (confirm('确定要禁用当前网址的高亮功能吗?')) {
                    disableUrl(currentPageUrl);
                }
            });
        }
        // 删除禁用项按钮
        sidebar.querySelectorAll('.disabled-item-remove').forEach(btn => {
            btn.addEventListener('click', (e) => {
                const type = e.target.dataset.type;
                const value = e.target.dataset.value;

                if (type === 'domain') {
                    enableDomain(value);
                } else if (type === 'url') {
                    enableUrl(value);
                }
            });
        });
        // 添加禁用域名
        const addDomainBtn = sidebar.querySelector('#add-domain-btn');
        if (addDomainBtn) {
            addDomainBtn.addEventListener('click', () => {
                const input = sidebar.querySelector('#add-domain-input');
                const domain = input.value.trim();

                if (domain) {
                    disableDomain(domain);
                    input.value = '';
                }
            });
        }
        // 添加禁用网址
        const addUrlBtn = sidebar.querySelector('#add-url-btn');
        if (addUrlBtn) {
            addUrlBtn.addEventListener('click', () => {
                const input = sidebar.querySelector('#add-url-input');
                const url = input.value.trim();

                if (url) {
                    disableUrl(url);
                    input.value = '';
                }
            });
        }
    }
    // 显示消息提示
    function showToast(message, type = 'info') {
        // 移除可能存在的旧toast
        const existingToast = document.querySelector('.highlight-toast');
        if (existingToast) {
            existingToast.remove();
        }
        // 创建toast元素
        const toast = document.createElement('div');
        toast.className = `highlight-toast ${type}`;
        toast.textContent = message;
        // 添加到页面
        document.body.appendChild(toast);
        // 短暂显示后自动消失
        setTimeout(() => {
            toast.classList.add('show');
            setTimeout(() => {
                toast.classList.remove('show');
                setTimeout(() => toast.remove(), 300); // 等待淡出动画完成后移除
            }, 2000);
        }, 10);
    }
    // 优化按钮添加函数,实现长按触发拖动
    function addToolbarButton() {
        // 从存储中读取按钮位置 - 修改为支持百分比值
        const savedPosition = GM_getValue('toolbar_position', { right: '20px', bottom: '20px' });
        const button = document.createElement('div');
        button.className = 'highlight-toolbar';
        // 根据设置决定初始显示状态
        if (!settings.showFloatingButton) {
            button.style.display = 'none';
        }
        // 使用更小的图标尺寸
        button.innerHTML = `
            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <line x1="3" y1="12" x2="21" y2="12"></line>
                <line x1="3" y1="6" x2="21" y2="6"></line>
                <line x1="3" y1="18" x2="21" y2="18"></line>
            </svg>
        `;
        // 应用保存的位置 - 优先使用相对于窗口边缘的定位
        if (savedPosition.usePercentage) {
            // 如果有百分比值,使用百分比定位
            button.style.right = savedPosition.rightPercent;
            button.style.bottom = savedPosition.bottomPercent;
            button.style.left = 'auto';
            button.style.top = 'auto';
        } else {
            // 否则尝试使用像素定位,但优先使用right/bottom
            if (savedPosition.right !== 'auto' && savedPosition.bottom !== 'auto') {
                button.style.right = savedPosition.right;
                button.style.bottom = savedPosition.bottom;
                button.style.left = 'auto';
                button.style.top = 'auto';
            } else {
                button.style.left = savedPosition.left || 'auto';
                button.style.top = savedPosition.top || 'auto';
                button.style.right = 'auto';
                button.style.bottom = 'auto';
            }
        }
        // 拖动相关变量
        let isDragging = false;
        let offsetX, offsetY;
        let originalPosition;
        let longPressTimer = null;
        let initialX, initialY;
        let hasMoved = false;
        let mouseDownTime = 0; // 添加按下时间记录
        // 添加一个标志来区分点击和拖动
        let isClickAllowed = true;
        // 修改直接点击事件处理
        button.addEventListener('click', function (e) {
            console.log('按钮点击事件触发, isClickAllowed:', isClickAllowed, 'isDragging:', isDragging);
            // 如果拖动结束后立即触发点击,可能是拖动后的松开,不应执行点击操作
            if (isDragging) {
                console.log('拖动状态,忽略点击');
                e.stopPropagation();
                return;
            }
            // 只有当点击被允许时才处理
            if (isClickAllowed) {
                console.log('浮动按钮点击,打开侧边栏');
                e.preventDefault(); // 阻止默认行为
                e.stopPropagation(); // 阻止冒泡
                // 确保侧边栏元素存在
                const sidebar = document.querySelector('.highlight-sidebar');
                if (!sidebar) {
                    console.warn("找不到侧边栏,尝试重新创建");
                    createSidebar();
                    setTimeout(() => toggleSidebar(true), 50); // 延迟切换确保DOM更新,强制设置为打开
                } else {
                    toggleSidebar(true); // 强制打开侧边栏,而不是切换状态
                }
            }
        });
        // 修改鼠标按下事件处理
        function handleTouchStart(e) {
            // 记录按下时间
            mouseDownTime = Date.now();
            // 每次触摸开始时重置标志
            isClickAllowed = true;
            // 记录初始接触位置
            initialX = e.clientX || (e.touches && e.touches[0].clientX);
            initialY = e.clientY || (e.touches && e.touches[0].clientY);
            hasMoved = false;
            // 保存原始位置
            originalPosition = {
                left: button.style.left,
                top: button.style.top,
                right: button.style.right,
                bottom: button.style.bottom
            };
            // 设置长按计时器
            longPressTimer = setTimeout(() => {
                // 长按后进入拖动模式
                isClickAllowed = false; // 禁止点击
                startDragging(e);
            }, 300); // 长按300ms触发拖动
            // 阻止移动设备上的默认行为
            if (e.type === 'touchstart') {
                e.preventDefault();
            }
        }
        // 启动拖动
        function startDragging(e) {
            // 清除长按计时器
            if (longPressTimer) {
                clearTimeout(longPressTimer);
                longPressTimer = null;
            }
            // 一旦开始拖动,就禁止点击
            isClickAllowed = false;
            // 如果是触摸事件,获取第一个触摸点
            const clientX = e.clientX || e.touches[0].clientX;
            const clientY = e.clientY || e.touches[0].clientY;
            // 计算偏移
            const rect = button.getBoundingClientRect();
            offsetX = clientX - rect.left;
            offsetY = clientY - rect.top;
            isDragging = true;
            button.classList.add('dragging');
            // 阻止默认事件和冒泡
            e.preventDefault();
            e.stopPropagation();
            // 添加临时全局事件监听
            document.addEventListener('mousemove', handleDragMove);
            document.addEventListener('touchmove', handleDragMove, { passive: false });
            document.addEventListener('mouseup', handleDragEnd);
            document.addEventListener('touchend', handleDragEnd);
        }
        // 处理移动
        function handleMove(e) {
            // 如果长按计时器存在,检查是否移动了足够距离取消长按
            if (longPressTimer) {
                const clientX = e.clientX || e.touches[0].clientX;
                const clientY = e.clientY || e.touches[0].clientY;
                // 计算移动距离
                const moveX = Math.abs(clientX - initialX);
                const moveY = Math.abs(clientY - initialY);

                // 如果移动超过阈值,取消长按并禁止点击
                if (moveX > 5 || moveY > 5) {
                    clearTimeout(longPressTimer);
                    longPressTimer = null;
                    hasMoved = true;
                    isClickAllowed = false; // 发生移动时禁止点击
                }
            }
            // 如果是拖动状态,处理拖动逻辑
            if (isDragging) {
                handleDragMove(e);
            }
        }
        // 拖动过程处理
        function handleDragMove(e) {
            if (!isDragging) return;
            // 如果是触摸事件,获取第一个触摸点
            const clientX = e.clientX || e.touches[0].clientX;
            const clientY = e.clientY || e.touches[0].clientY;
            // 计算新位置
            const newLeft = clientX - offsetX;
            const newTop = clientY - offsetY;
            // 限制在视口内
            const buttonWidth = button.offsetWidth;
            const buttonHeight = button.offsetHeight;
            const maxX = window.innerWidth - buttonWidth;
            const maxY = window.innerHeight - buttonHeight;
            const boundedLeft = Math.max(0, Math.min(newLeft, maxX));
            const boundedTop = Math.max(0, Math.min(newTop, maxY));
            // 修改为绝对定位方式,使用left/top而非right/bottom
            button.style.left = `${boundedLeft}px`;
            button.style.top = `${boundedTop}px`;
            button.style.right = 'auto';
            button.style.bottom = 'auto';
            // 阻止默认事件
            e.preventDefault();
        }
        // 处理触摸或鼠标结束
        function handleTouchEnd(e) {
            // 清除长按计时器
            if (longPressTimer) {
                clearTimeout(longPressTimer);
                longPressTimer = null;
            }
            // 如果正在拖动,结束拖动
            if (isDragging) {
                handleDragEnd(e);
                return;
            }
        }
        // 拖动结束处理 - 修改为使用百分比定位
        function handleDragEnd(e) {
            if (!isDragging) return;
            // 计算拖动时间
            const dragDuration = Date.now() - mouseDownTime;
            // 如果拖动时间很短(小于200ms),可能是用户想点击而不是拖动
            if (dragDuration < 200 && !hasMoved) {
                isClickAllowed = true;
            } else {
                // 设置一个短暂的标志,防止拖动结束后的点击被误触发
                isClickAllowed = false;
                setTimeout(() => { isClickAllowed = true; }, 300);
            }
            isDragging = false;
            button.classList.remove('dragging');
            // 移除临时事件监听
            document.removeEventListener('mousemove', handleDragMove);
            document.removeEventListener('touchmove', handleDragMove);
            document.removeEventListener('mouseup', handleDragEnd);
            document.removeEventListener('touchend', handleDragEnd);
            // 计算相对于窗口边缘的距离(使用百分比)
            const rect = button.getBoundingClientRect();
            const rightDistance = window.innerWidth - (rect.left + rect.width);
            const bottomDistance = window.innerHeight - (rect.top + rect.height);
            // 决定使用哪种定位方式 - 如果接近边缘,使用相对于边缘的定位
            const EDGE_THRESHOLD = 100; // 100px的边缘阈值
            let position;
            if (rightDistance <= EDGE_THRESHOLD || bottomDistance <= EDGE_THRESHOLD) {
                // 如果接近右边或底部边缘,使用right/bottom定位
                const rightPercent = (rightDistance / window.innerWidth * 100).toFixed(2) + '%';
                const bottomPercent = (bottomDistance / window.innerHeight * 100).toFixed(2) + '%';
                position = {
                    rightPercent: rightPercent,
                    bottomPercent: bottomPercent,
                    right: rightDistance + 'px',
                    bottom: bottomDistance + 'px',
                    left: 'auto',
                    top: 'auto',
                    usePercentage: true
                };
                // 立即应用百分比定位,保持按钮位置不变
                button.style.right = rightPercent;
                button.style.bottom = bottomPercent;
                button.style.left = 'auto';
                button.style.top = 'auto';
            } else {
                // 使用left/top定位,但同样记录百分比值
                const leftPercent = (rect.left / window.innerWidth * 100).toFixed(2) + '%';
                const topPercent = (rect.top / window.innerHeight * 100).toFixed(2) + '%';
                position = {
                    leftPercent: leftPercent,
                    topPercent: topPercent,
                    left: rect.left + 'px',
                    top: rect.top + 'px',
                    right: 'auto',
                    bottom: 'auto',
                    usePercentage: true
                };
            }
            // 保存新位置
            GM_setValue('toolbar_position', position);
        }
        // 绑定事件 - 使用统一的触摸/鼠标事件处理逻辑
        button.addEventListener('mousedown', handleTouchStart);
        button.addEventListener('touchstart', handleTouchStart, { passive: false });
        button.addEventListener('mousemove', handleMove);
        button.addEventListener('touchmove', handleMove, { passive: false });
        button.addEventListener('mouseup', handleTouchEnd);
        button.addEventListener('touchend', handleTouchEnd);
        document.body.appendChild(button);
        // 添加窗口大小变化监听,确保按钮始终可见
        window.addEventListener('resize', function () {
            // 获取按钮当前位置
            const rect = button.getBoundingClientRect();
            // 检查按钮是否在视口内
            const isInViewport = (
                rect.top >= 0 &&
                rect.left >= 0 &&
                rect.bottom <= window.innerHeight &&
                rect.right <= window.innerWidth
            );
            // 如果按钮不在视口内,重新定位到可见区域
            if (!isInViewport) {
                console.log('按钮不在视口内,重新定位');
                // 获取保存的位置信息
                const savedPos = GM_getValue('toolbar_position', { right: '20px', bottom: '20px' });
                // 如果使用的是百分比定位,应用百分比
                if (savedPos.usePercentage) {
                    if (savedPos.rightPercent && savedPos.bottomPercent) {
                        button.style.right = savedPos.rightPercent;
                        button.style.bottom = savedPos.bottomPercent;
                        button.style.left = 'auto';
                        button.style.top = 'auto';
                    } else if (savedPos.leftPercent && savedPos.topPercent) {
                        // 检查左/上百分比是否会导致按钮超出视口
                        const leftPct = parseFloat(savedPos.leftPercent);
                        const topPct = parseFloat(savedPos.topPercent);

                        if (leftPct > 95 || topPct > 95) {
                            // 如果百分比过大,重置到默认位置
                            button.style.right = '20px';
                            button.style.bottom = '20px';
                            button.style.left = 'auto';
                            button.style.top = 'auto';
                        } else {
                            button.style.left = savedPos.leftPercent;
                            button.style.top = savedPos.topPercent;
                            button.style.right = 'auto';
                            button.style.bottom = 'auto';
                        }
                    }
                } else {
                    // 回退到安全的默认位置
                    button.style.right = '20px';
                    button.style.bottom = '20px';
                    button.style.left = 'auto';
                    button.style.top = 'auto';
                    // 更新保存的位置
                    const newPosition = {
                        right: '20px',
                        bottom: '20px',
                        rightPercent: '5%',
                        bottomPercent: '5%',
                        left: 'auto',
                        top: 'auto',
                        usePercentage: true
                    };
                    GM_setValue('toolbar_position', newPosition);
                }
                // 确保按钮位置有效
                validateButtonPosition(button);
            }
        });
        // 初始验证按钮位置
        validateButtonPosition(button);
    }
    // 验证按钮位置并确保在视口内
    function validateButtonPosition(button) {
        // 等待布局完成再检查位置
        setTimeout(() => {
            const rect = button.getBoundingClientRect();
            // 检查按钮是否完全在视口外
            if (rect.left > window.innerWidth || rect.top > window.innerHeight ||
                rect.right < 0 || rect.bottom < 0) {
                console.log('按钮在视口外,重置位置');
                // 重置到默认位置
                button.style.right = '20px';
                button.style.bottom = '20px';
                button.style.left = 'auto';
                button.style.top = 'auto';
                // 更新保存的位置
                const newPosition = {
                    right: '20px',
                    bottom: '20px',
                    rightPercent: '5%',
                    bottomPercent: '5%',
                    left: 'auto',
                    top: 'auto',
                    usePercentage: true
                };
                GM_setValue('toolbar_position', newPosition);
            }
        }, 100);
    }
    // 获取range内的所有文本节点
    function getAllTextNodesInRange(range) {
        const textNodes = [];
        // 创建文本节点迭代器
        const walker = document.createTreeWalker(
            range.commonAncestorContainer,
            NodeFilter.SHOW_TEXT,
            {
                acceptNode: function (node) {
                    // 检查节点是否在范围内
                    if (range.intersectsNode(node)) {
                        return NodeFilter.FILTER_ACCEPT;
                    }
                    return NodeFilter.FILTER_REJECT;
                }
            }
        );
        // 收集所有文本节点
        let node;
        while (node = walker.nextNode()) {
            textNodes.push(node);
        }
        return textNodes;
    }
    // 检查节点是否已在高亮元素内
    function isInsideHighlight(node) {
        let parent = node.parentNode;
        while (parent) {
            if (parent.classList && parent.classList.contains('highlight-marked')) {
                return true;
            }
            parent = parent.parentNode;
        }
        return false;
    }
    // 删除高亮
    function removeHighlight() {
        const selection = window.getSelection();
        if (!selection.toString().trim()) {
            return;
        }
        // 尝试查找选中文本对应的已存在高亮
        const selectedText = selection.toString().trim();
        const existingHighlight = highlights.find(h => h.text.trim() === selectedText);

        if (existingHighlight) {
            removeHighlightById(existingHighlight.id);
        } else {
            console.log('没有找到匹配的高亮记录');
        }
    }
    // 通过ID删除高亮
    function removeHighlightById(id) {
        // 删除DOM中的高亮元素
        const highlightElements = document.querySelectorAll(`.highlight-marked[data-id="${id}"]`);
        highlightElements.forEach(el => {
            const parent = el.parentNode;
            // 将所有子元素移回父元素
            while (el.firstChild) {
                parent.insertBefore(el.firstChild, el);
            }
            // 移除高亮元素本身
            parent.removeChild(el);
        });
        // 从存储中删除
        const index = highlights.findIndex(h => h.id === id);
        if (index !== -1) {
            highlights.splice(index, 1);
            saveHighlights();
            refreshHighlightsList();
        }
    }
    // 安全地高亮复杂选择范围 (完整版)
    function safelyHighlightComplexRange(range, id, color) {
        console.log('使用安全高亮方法处理复杂选择');
        // 获取所有在范围内的文本节点
        const nodes = getAllTextNodesInRange(range);
        // 保存起始和结束信息,以便正确处理部分选择的节点
        const startNode = range.startContainer;
        const startOffset = range.startOffset;
        const endNode = range.endContainer;
        const endOffset = range.endOffset;
        nodes.forEach(node => {
            // 跳过已经在高亮元素内的文本节点
            if (isInsideHighlight(node)) {
                console.log('跳过已高亮的节点');
                return;
            }
            // 确定需要高亮的文本范围
            let nodeStart = 0;
            let nodeEnd = node.length;
            // 处理起始节点
            if (node === startNode) {
                nodeStart = startOffset;
            }
            // 处理结束节点
            if (node === endNode) {
                nodeEnd = endOffset;
            }
            // 如果节点需要部分高亮且有内容要高亮
            if (nodeStart < nodeEnd) {
                try {
                    // 创建新的范围来高亮当前节点部分
                    const nodeRange = document.createRange();
                    nodeRange.setStart(node, nodeStart);
                    nodeRange.setEnd(node, nodeEnd);
                    // 创建高亮元素
                    const span = document.createElement('span');
                    span.className = 'highlight-marked';
                    span.style.backgroundColor = color;
                    span.dataset.id = id;
                    // 将选中内容替换为高亮元素
                    try {
                        nodeRange.surroundContents(span);
                        // 添加点击事件监听器
                        span.addEventListener('click', (e) => {
                            e.stopPropagation();
                            showHighlightContextMenu(e, id);
                        });
                    } catch (e) {
                        console.error('无法高亮复杂范围的部分节点:', e);
                    }
                } catch (e) {
                    console.error('处理部分节点时出错:', e);
                }
            }
        });
    }
    // 整合后的应用高亮函数
    function applyHighlights() {
        let successCount = 0;
        let failedCount = 0;
        highlights.forEach(highlight => {
            try {
                console.log(`尝试恢复高亮ID: ${highlight.id}, 文本: "${highlight.text.substring(0, 30)}..."`);
                let restored = false;
                // 先尝试通过DOM路径恢复
                const range = constructRangeFromPath(highlight.path);
                if (range) {
                    // 如果找到了范围,使用它
                    if (applyHighlightToRange(range, highlight)) {
                        console.log(`通过DOM路径成功恢复高亮: ${highlight.id}`);
                        successCount++;
                        restored = true;
                    }
                }
                // DOM路径失败,尝试文本匹配
                if (!restored && highlight.text) {
                    console.log(`尝试通过文本内容匹配: "${highlight.text.substring(0, 30)}..."`);
                    // 如果文本长度合适,尝试在页面中查找
                    if (findAndHighlightText(highlight)) {
                        console.log(`通过文本匹配成功恢复高亮: ${highlight.id}`);
                        successCount++;
                        restored = true;
                    }
                }
                // 所有方法都失败了
                if (!restored) {
                    console.warn(`无法恢复高亮 ID: ${highlight.id}`);
                    failedCount++;
                }
            } catch (e) {
                console.error('应用高亮时出错:', e, highlight);
                failedCount++;
            }
        });
        console.log(`高亮恢复统计: 成功=${successCount}, 失败=${failedCount}, 总计=${highlights.length}`);
    }
    // 添加新函数:设置标题编辑功能
    function setupTitleEditing(sidebar) {
        const titleElement = sidebar.querySelector('.sidebar-description');
        if (!titleElement) return;
        // 双击开始编辑
        titleElement.addEventListener('dblclick', function (e) {
            // 获取当前标题文本 - 直接使用完整标题
            const currentText = settings.sidebarDescription || '网页划词高亮工具';
            // 切换为编辑模式
            titleElement.classList.add('editing');
            titleElement.setAttribute('contenteditable', 'true');
            titleElement.setAttribute('spellcheck', 'false');
            // 直接显示当前文本,不需要分离
            titleElement.textContent = currentText;
            // 聚焦并全选文本
            titleElement.focus();
            document.execCommand('selectAll', false, null);
            // 阻止事件冒泡
            e.stopPropagation();
        });
        // 保存编辑(失去焦点时)
        titleElement.addEventListener('blur', function () {
            saveEditedTitle(titleElement);
        });
        // 按下回车键保存
        titleElement.addEventListener('keydown', function (e) {
            if (e.key === 'Enter') {
                e.preventDefault(); // 防止插入换行符
                titleElement.blur(); // 触发blur事件保存编辑
            } else if (e.key === 'Escape') {
                // ESC键取消编辑
                titleElement.textContent = settings.sidebarDescription || '网页划词高亮工具';
                titleElement.removeAttribute('contenteditable');
                titleElement.classList.remove('editing');
                e.preventDefault();
            }
        });
    }
    // 添加新函数:保存编辑后的标题
    function saveEditedTitle(titleElement) {
        if (!titleElement.hasAttribute('contenteditable')) return;
        // 获取编辑后的文本并清理
        let newTitle = titleElement.textContent.trim();
        // 如果为空,使用默认值
        if (!newTitle) {
            newTitle = '网页划词高亮工具';
        }
        // 更新设置
        settings.sidebarDescription = newTitle;
        saveSettings();
        // 恢复显示格式
        titleElement.removeAttribute('contenteditable');
        titleElement.classList.remove('editing');
        // 更新显示
        updateSidebarDescription();
        showToast('标题已更新');
    }
    // 更新侧边栏描述
    function updateSidebarDescription() {
        const description = document.querySelector('.sidebar-description');
        if (description && !description.classList.contains('editing')) {
            const customText = settings.sidebarDescription || '网页划词高亮工具';
            description.textContent = customText;
        }
    }
    // 切换浮动按钮显示状态的函数
    function toggleFloatingButton() {
        settings.showFloatingButton = !settings.showFloatingButton;
        saveSettings();
        // 更新按钮显示状态
        const floatingButton = document.querySelector('.highlight-toolbar');
        if (floatingButton) {
            if (settings.showFloatingButton) {
                floatingButton.style.display = 'flex';
                showToast('已显示浮动按钮');
            } else {
                floatingButton.style.display = 'none';
                showToast('已隐藏浮动按钮,可通过菜单重新显示');
            }
        }
    }
    // 初始化
    init();
})();