Greasy Fork

Greasy Fork is available in English.

网页划词高亮工具

提供网页划词高亮功能

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==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();
})();