GMGN 前排统计

统计GMGN任意代币前排地址的数据,让数字来说话!新增首次记录和涨跌提醒功能,所有数字可点击查看详情,弹框显示净流入数据,负数红色显示,点击外部关闭

当前为 2025-08-15 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         GMGN 前排统计
// @namespace    http://tampermonkey.net/
// @version      4.8
// @description  统计GMGN任意代币前排地址的数据,让数字来说话!新增首次记录和涨跌提醒功能,所有数字可点击查看详情,弹框显示净流入数据,负数红色显示,点击外部关闭
// @match        https://gmgn.ai/*
// @match        https://www.gmgn.ai/*
// @require      https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js
// @require      https://code.jquery.com/jquery-3.6.0.min.js
// @grant        none
// @run-at       document-start
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // 全局变量 - 跟踪下载按钮状态
    let isDownloadInProgress = false;
    let currentCAAddress = '';

    // 现代化提示框函数
    function showModernToast(message, type = 'success', duration = 3000) {
        // 移除现有的提示框
        const existingToast = document.querySelector('.modern-toast');
        const existingOverlay = document.querySelector('.modern-toast-overlay');
        if (existingToast) existingToast.remove();
        if (existingOverlay) existingOverlay.remove();

        // 创建遮罩层
        const overlay = document.createElement('div');
        overlay.className = 'modern-toast-overlay';

        // 创建提示框
        const toast = document.createElement('div');
        toast.className = 'modern-toast';

        // 根据类型设置图标
        let icon, iconClass;
        switch (type) {
            case 'success':
                icon = '✓';
                iconClass = 'success';
                break;
            case 'error':
                icon = '✕';
                iconClass = 'error';
                break;
            case 'info':
                icon = 'ℹ';
                iconClass = 'info';
                break;
            default:
                icon = '✓';
                iconClass = 'success';
        }

        toast.innerHTML = `
            <div class="modern-toast-content">
                <div class="modern-toast-icon ${iconClass}">${icon}</div>
                <div class="modern-toast-text">${message}</div>
                <button class="modern-toast-close">&times;</button>
            </div>
        `;

        // 添加到页面
        document.body.appendChild(overlay);
        document.body.appendChild(toast);

        // 关闭函数
        const closeToast = () => {
            toast.style.animation = 'toastSlideOut 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards';
            overlay.style.animation = 'overlayFadeIn 0.3s ease reverse';
            setTimeout(() => {
                if (toast.parentNode) toast.remove();
                if (overlay.parentNode) overlay.remove();
            }, 300);
        };

        // 绑定关闭事件
        const closeBtn = toast.querySelector('.modern-toast-close');
        closeBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            closeToast();
        });

        // 点击遮罩层关闭
        overlay.addEventListener('click', closeToast);

        // 点击提示框本身也可以关闭
        toast.addEventListener('click', closeToast);

        // 自动关闭
        if (duration > 0) {
            setTimeout(closeToast, duration);
        }

        // ESC键关闭
        const escHandler = (e) => {
            if (e.key === 'Escape') {
                closeToast();
                document.removeEventListener('keydown', escHandler);
            }
        };
        document.addEventListener('keydown', escHandler);

        // 返回关闭函数,允许手动关闭
        return closeToast;
    }

    // 动态添加 CSS
    const style = document.createElement('style');
    style.textContent = `
    .statistic-gmgn-stats-container {
        background-color: transparent;
        border-radius: 4px;
        font-family: Arial, sans-serif;
        margin-right: 8px;
        margin-bottom:8px;
        border: 1px solid #333;
        /* 精细的右侧和下侧发光效果 */
        box-shadow:
            2px 2px 4px rgba(0, 119, 255, 0.6),  /* 右下外发光(更小的偏移和模糊) */
            1px 1px 2px rgba(0, 119, 255, 0.4),  /* 精细的次级发光 */
            inset 0 0 3px rgba(0, 119, 255, 0.2); /* 更细腻的内发光 */
        padding: 4px 6px;
        max-width: fit-content;
    }
    .statistic-gmgn-stats-header, .statistic-gmgn-stats-data {
        display: grid;
        grid-template-columns: repeat(12, 1fr);
        text-align: center;
        gap: 6px;
        font-weight: normal;
        font-size: 13px;
    }
    .statistic-gmgn-stats-header.sol-network, .statistic-gmgn-stats-data.sol-network {
        grid-template-columns: repeat(13, minmax(auto, 1fr));
        gap: 4px;
        font-size: 12px;
    }
    .statistic-gmgn-stats-header span {
        color: #ccc;
        font-weight: normal;
        padding: 1px 2px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .statistic-gmgn-stats-header.sol-network span {
        font-size: 11px;
        padding: 1px;
    }
    .statistic-gmgn-stats-data span {
        color: #00ff00;
        font-weight: normal;
        cursor: default;
        transition: all 0.2s ease;
        padding: 1px 3px;
        border-radius: 2px;
        min-width: 0;
        white-space: nowrap;
    }
    .statistic-gmgn-stats-data span.clickable {
        cursor: pointer;
    }
    .statistic-gmgn-stats-data span.clickable:hover {
        background-color: rgba(0, 255, 0, 0.1);
        border-radius: 3px;
        transform: scale(1.03);
    }
    .statistic-gmgn-stats-data.sol-network span {
        padding: 1px 2px;
        font-size: 12px;
    }
    .statistic-gmgn-stats-data span .statistic-up-arrow,
    .statistic-up-arrow {
        color: green !important;
        margin-left: 2px;
        font-weight: bold;
    }
    .statistic-gmgn-stats-data span .statistic-down-arrow,
    .statistic-down-arrow {
        color: red !important;
        margin-left: 2px;
        font-weight: bold;
    }




    /* 完整弹框CSS样式 - 现代化设计 */
    .statistic-gmgn-modal {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                background: linear-gradient(135deg, rgba(0, 0, 0, 0.4), rgba(15, 23, 42, 0.8));
                backdrop-filter: blur(8px);
                display: flex;
                align-items: center;
                justify-content: center;
                z-index: 1000;
                animation: modalFadeIn 0.3s ease-out;
    }
    .statistic-gmgn-modal-content {
        background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%) !important;
        border-radius: 16px !important;
        width: 85% !important;
        max-width: 900px !important;
        max-height: 85vh !important;
        overflow-y: auto !important;
        padding: 24px !important;
        color: white !important;
        position: fixed !important;
        top: 50% !important;
        left: 50% !important;
        transform: translate(-50%, -50%) scale(0.95) !important;
        box-shadow:
            0 25px 50px -12px rgba(0, 0, 0, 0.6),
            0 0 0 1px rgba(255, 255, 255, 0.05),
            inset 0 1px 0 0 rgba(255, 255, 255, 0.1) !important;
        margin: 0 !important;
        z-index: 100000 !important;
        box-sizing: border-box !important;
        min-height: auto !important;
        min-width: 320px !important;
        pointer-events: auto !important;
        animation: modalSlideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards !important;
        /* 性能优化 - 硬件加速 */
        will-change: transform, opacity !important;
        transform-style: preserve-3d !important;
        backface-visibility: hidden !important;
        contain: layout style paint !important;
        /* 优化滚动性能 */
        overflow-anchor: none !important;
        scroll-behavior: smooth !important;
        -webkit-overflow-scrolling: touch !important;
    }
    .statistic-gmgn-modal-header {
        display: flex !important;
        justify-content: space-between !important;
        align-items: center !important;
        margin-bottom: 24px !important;
        padding: 16px 20px !important;
        margin: -24px -24px 24px -24px !important;
        background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, rgba(139, 92, 246, 0.1) 100%) !important;
        border-radius: 16px 16px 0 0 !important;
        border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
        backdrop-filter: blur(10px) !important;
    }
    .statistic-gmgn-modal-title {
        font-size: 20px !important;
        font-weight: 700 !important;
        color: white !important;
        margin: 0 !important;
        background: linear-gradient(135deg, #ffffff 0%, #e2e8f0 100%) !important;
        background-clip: text !important;
        -webkit-background-clip: text !important;
        -webkit-text-fill-color: transparent !important;
        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3) !important;
    }
    .statistic-gmgn-modal-close {
        background: rgba(148, 163, 184, 0.1) !important;
        border: 1px solid rgba(148, 163, 184, 0.2) !important;
        color: #94a3b8 !important;
        font-size: 18px !important;
        cursor: pointer !important;
        padding: 8px !important;
        line-height: 1 !important;
        width: 36px !important;
        height: 36px !important;
        border-radius: 50% !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
    }
    .statistic-gmgn-modal-close:hover {
        color: #fff !important;
        background: linear-gradient(135deg, #ef4444, #dc2626) !important;
        border-color: #ef4444 !important;
        transform: scale(1.1) !important;
        box-shadow: 0 4px 12px rgba(239, 68, 68, 0.4) !important;
    }
    .statistic-gmgn-result-item {
        background: linear-gradient(135deg, rgba(51, 65, 85, 0.6) 0%, rgba(30, 41, 59, 0.4) 100%);
        border-radius: 12px;
        padding: 16px;
        margin-bottom: 16px;
        border: 1px solid rgba(255, 255, 255, 0.1);
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        position: relative;
        overflow: hidden;
        /* 性能优化 - 硬件加速 */
        will-change: transform, opacity;
        transform: translateZ(0);
        backface-visibility: hidden;
        contain: layout style;
        /* 减少backdrop-filter在大数据量时的性能消耗 */
    }
    .statistic-gmgn-result-item::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 2px;
        background: linear-gradient(90deg, #3b82f6, #8b5cf6, #06b6d4);
        opacity: 0;
        transition: opacity 0.3s ease;
        transform: translateZ(0);
    }
    .statistic-gmgn-result-item:hover {
        background: linear-gradient(135deg, rgba(51, 65, 85, 0.8) 0%, rgba(30, 41, 59, 0.6) 100%);
        transform: translateY(-2px) translateZ(0);
        box-shadow:
            0 8px 16px rgba(0, 0, 0, 0.15),
            0 0 0 1px rgba(255, 255, 255, 0.1);
        border-color: rgba(59, 130, 246, 0.3);
    }
    .statistic-gmgn-result-item:hover::before {
        opacity: 1;
    }
    .statistic-gmgn-analysis-summary {
        margin-bottom: 24px;
        padding: 20px;
        background: linear-gradient(135deg, rgba(38, 50, 56, 0.6) 0%, rgba(30, 41, 59, 0.8) 100%);
        border-radius: 12px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border: 1px solid rgba(255, 255, 255, 0.1);
        backdrop-filter: blur(10px);
        box-shadow:
            0 8px 32px rgba(0, 0, 0, 0.3),
            inset 0 1px 0 rgba(255, 255, 255, 0.1);
    }
    .statistic-gmgn-summary-stats {
        display: flex;
        gap: 32px;
        flex-wrap: wrap;
    }
    .statistic-gmgn-stat-item {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        padding: 8px 12px;
        background: rgba(255, 255, 255, 0.05);
        border-radius: 8px;
        border: 1px solid rgba(255, 255, 255, 0.1);
        transition: all 0.3s ease;
        min-width: 80px;
    }
    .statistic-gmgn-stat-item:hover {
        background: rgba(255, 255, 255, 0.1);
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);
    }
    .statistic-gmgn-stat-label {
        color: #94a3b8;
        font-size: 12px;
        font-weight: 500;
        margin-bottom: 4px;
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }
    .statistic-gmgn-stat-value {
        font-weight: 700;
        font-size: 18px;
        background: linear-gradient(135deg, #3b82f6, #8b5cf6);
        background-clip: text;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
        text-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
    }
    .statistic-gmgn-result-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 8px;
        flex-wrap: wrap;
        gap: 8px;
    }
    .statistic-gmgn-result-rank {
        font-size: 14px;
        color: #94a3b8;
        font-weight: 600;
        min-width: 30px;
    }
    .statistic-gmgn-result-address {
        font-weight: 600;
        word-break: break-all;
        cursor: pointer;
        padding: 8px 12px;
        border-radius: 8px;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        background: linear-gradient(135deg, rgba(71, 85, 105, 0.6), rgba(51, 65, 85, 0.8));
        border: 1px solid rgba(0, 255, 136, 0.3);
        flex: 1;
        min-width: 200px;
        color: #00ff88;
        font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
        font-size: 13px;
        position: relative;
        overflow: hidden;
    }
    .statistic-gmgn-result-address::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(90deg, transparent, rgba(0, 255, 136, 0.2), transparent);
        transition: left 0.5s ease;
    }
    .statistic-gmgn-result-address:hover {
        background: linear-gradient(135deg, rgba(0, 255, 136, 0.1), rgba(51, 65, 85, 0.9));
        border-color: #00ff88;
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0, 255, 136, 0.3);
    }
    .statistic-gmgn-result-address:hover::before {
        left: 100%;
    }
    .statistic-gmgn-detail-section {
        margin-bottom: 12px;
    }
    .statistic-gmgn-section-title {
        font-size: 13px;
        font-weight: 600;
        color: #94a3b8;
        margin-bottom: 8px;
        display: flex;
        align-items: center;
        flex-wrap: wrap;
    }
    .statistic-gmgn-detail-grid {
        display: grid;
        grid-template-columns: 80px 1fr 80px 1fr;
        gap: 4px 8px;
        align-items: start;
        font-size: 12px;
    }
    .statistic-gmgn-detail-label {
        color: #94a3b8;
        font-size: 12px;
        padding: 2px 0;
        align-self: start;
    }
    .statistic-gmgn-detail-value {
        font-size: 12px;
        color: #e2e8f0;
        padding: 2px 0;
        word-break: break-word;
        line-height: 1.4;
    }
    .statistic-gmgn-value-highlight {
        color: #3b82f6;
        font-weight: 600;
    }
    .statistic-gmgn-compact-details .statistic-gmgn-detail-section {
        margin-bottom: 8px;
    }
    .statistic-gmgn-compact-details .statistic-gmgn-detail-section {
        margin-left: 10px;
    }
    .statistic-gmgn-address-jump-btn {
        background: linear-gradient(135deg, #10b981, #059669);
        color: white;
        padding: 6px 12px;
        border-radius: 8px;
        font-size: 11px;
        font-weight: 600;
        margin-left: 12px;
        cursor: pointer;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        text-decoration: none;
        display: inline-flex;
        align-items: center;
        gap: 4px;
        border: 1px solid rgba(16, 185, 129, 0.3);
        position: relative;
        overflow: hidden;
        box-shadow: 0 2px 8px rgba(16, 185, 129, 0.2);
    }
    .statistic-gmgn-address-jump-btn::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
        transition: left 0.4s ease;
    }
    .statistic-gmgn-address-jump-btn:hover {
        background: linear-gradient(135deg, #059669, #047857);
        transform: translateY(-2px) scale(1.05);
        box-shadow: 0 4px 16px rgba(16, 185, 129, 0.4);
        border-color: #10b981;
    }
    .statistic-gmgn-address-jump-btn:hover::before {
        left: 100%;
    }
    .statistic-gmgn-address-jump-btn:active {
        transform: translateY(0) scale(1);
    }

    .statistic-gmgn-profit-positive {
        color: #00ff88 !important;
    }

    .statistic-gmgn-profit-negative {
        color: #ff4444 !important;
    }

    .statistic-gmgn-empty-message {
        text-align: center;
        color: #ccc;
        padding: 20px;
        margin: 0;
    }

    .statistic-gmgn-stats-info {
        text-align: center !important;
        margin-bottom: 15px !important;
        padding: 10px !important;
        background: rgba(0, 119, 255, 0.1) !important;
        border-radius: 8px !important;
        border: 1px solid rgba(0, 119, 255, 0.3) !important;
        color: #fff !important;
        font-size: 14px !important;
    }

    .statistic-gmgn-export-btn {
        background: linear-gradient(135deg, #10b981, #059669) !important;
        color: white !important;
        border: 1px solid rgba(16, 185, 129, 0.3) !important;
        padding: 12px 20px !important;
        border-radius: 12px !important;
        font-size: 13px !important;
        font-weight: 600 !important;
        cursor: pointer !important;
        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
        display: flex !important;
        align-items: center !important;
        gap: 8px !important;
        position: relative !important;
        overflow: hidden !important;
        box-shadow: 0 4px 12px rgba(16, 185, 129, 0.2) !important;
    }
    .statistic-gmgn-export-btn::before {
        content: '';
        position: absolute;
        top: 0;
        left: -100%;
        width: 100%;
        height: 100%;
        background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
        transition: left 0.5s ease;
    }
    .statistic-gmgn-export-btn:hover {
        background: linear-gradient(135deg, #059669, #047857) !important;
        transform: translateY(-2px) !important;
        box-shadow: 0 8px 24px rgba(16, 185, 129, 0.4) !important;
        border-color: #10b981 !important;
    }
    .statistic-gmgn-export-btn:hover::before {
        left: 100% !important;
    }
    .statistic-gmgn-export-btn:active {
        transform: translateY(0) !important;
        box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3) !important;
    }

    /* 动画关键帧 */
    @keyframes modalFadeIn {
        from {
            opacity: 0;
        }
        to {
            opacity: 1;
        }
    }

    @keyframes modalSlideIn {
        from {
            opacity: 0;
            transform: translate(-50%, -50%) scale(0.8) rotateY(-10deg);
        }
        to {
            opacity: 1;
            transform: translate(-50%, -50%) scale(1) rotateY(0deg);
        }
    }

    /* 响应式设计优化 */
    @media (max-width: 768px) {
        .statistic-gmgn-modal-content {
            width: 95% !important;
            padding: 16px !important;
            margin: 10px !important;
        }

        .statistic-gmgn-modal-header {
            padding: 12px 16px !important;
            margin: -16px -16px 16px -16px !important;
        }

        .statistic-gmgn-summary-stats {
            gap: 16px;
            flex-wrap: wrap;
        }

        .statistic-gmgn-stat-item {
            min-width: 60px;
            padding: 6px 8px;
        }

        .statistic-gmgn-result-address {
            font-size: 11px;
            padding: 6px 8px;
        }
    }

    /* 自定义滚动条 */
    .statistic-gmgn-modal-content::-webkit-scrollbar {
        width: 8px;
    }

    .statistic-gmgn-modal-content::-webkit-scrollbar-track {
        background: rgba(0, 0, 0, 0.1);
        border-radius: 4px;
    }

    .statistic-gmgn-modal-content::-webkit-scrollbar-thumb {
        background: linear-gradient(135deg, #3b82f6, #8b5cf6);
        border-radius: 4px;
    }

    .statistic-gmgn-modal-content::-webkit-scrollbar-thumb:hover {
        background: linear-gradient(135deg, #2563eb, #7c3aed);
    }

    /* 加载状态动画 */
    @keyframes pulse {
        0%, 100% {
            opacity: 1;
        }
        50% {
            opacity: 0.5;
        }
    }

    .statistic-gmgn-loading {
        animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
    }

    /* 分页控制样式 */
    .statistic-gmgn-pagination-info {
        background: linear-gradient(135deg, rgba(59, 130, 246, 0.1), rgba(139, 92, 246, 0.1));
        border: 1px solid rgba(59, 130, 246, 0.3);
        border-radius: 8px;
        padding: 8px 12px;
        margin-bottom: 16px;
        text-align: center;
    }

    .statistic-pagination-text {
        color: #3b82f6;
        font-size: 12px;
        font-weight: 500;
    }

    .statistic-gmgn-pagination-controls {
        display: flex;
        justify-content: space-between;
        align-items: center;
        padding: 16px 20px;
        margin: 16px -24px -24px -24px;
        background: linear-gradient(135deg, rgba(30, 41, 59, 0.8), rgba(15, 23, 42, 0.9));
        border-radius: 0 0 16px 16px;
        border-top: 1px solid rgba(255, 255, 255, 0.1);
    }

    .statistic-pagination-btn {
        background: linear-gradient(135deg, #3b82f6, #8b5cf6);
        color: white;
        border: none;
        padding: 8px 16px;
        border-radius: 8px;
        font-size: 12px;
        font-weight: 600;
        cursor: pointer;
        transition: all 0.3s ease;
        transform: translateZ(0);
    }

    .statistic-pagination-btn:hover:not(:disabled) {
        background: linear-gradient(135deg, #2563eb, #7c3aed);
        transform: translateY(-1px);
        box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
    }

    .statistic-pagination-btn:disabled {
        background: rgba(148, 163, 184, 0.3);
        color: rgba(148, 163, 184, 0.6);
        cursor: not-allowed;
        transform: none;
    }

    .statistic-pagination-current {
        color: #e2e8f0;
        font-size: 13px;
        font-weight: 500;
    }

    /* 可疑地址类型标识样式 */
    .statistic-suspicious-labels {
        display: inline-flex;
        gap: 6px;
        flex-wrap: wrap;
        margin-left: 12px;
        align-items: center;
    }

    .statistic-suspicious-label {
        font-size: 10px;
        font-weight: 600;
        padding: 2px 6px;
        border-radius: 10px;
        border: 1px solid;
        white-space: nowrap;
        display: inline-flex;
        align-items: center;
        gap: 3px;
        text-transform: uppercase;
        letter-spacing: 0.3px;
        transition: all 0.2s ease;
        cursor: default;
    }

    .statistic-suspicious-label:hover {
        transform: scale(1.05);
        box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
    }

    .statistic-suspicious-label::before {
        content: '⚠';
        font-size: 8px;
    }

    .statistic-suspicious-label.rat-trader::before {
        content: '🐭';
    }

    .statistic-suspicious-label.transfer-in::before {
        content: '⬇';
    }

    .statistic-suspicious-label.bundler::before {
        content: '📦';
    }

    /* 现代化详情数据样式 */
    .statistic-detail-grid-modern {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
        gap: 12px;
        padding: 8px 0;
    }

    .statistic-detail-item {
        display: flex;
        align-items: center;
        background: rgba(255, 255, 255, 0.03);
        border: 1px solid rgba(255, 255, 255, 0.08);
        border-radius: 8px;
        padding: 8px 10px;
        transition: all 0.3s ease;
        position: relative;
        overflow: hidden;
        min-height: 48px;
    }

    .statistic-detail-item::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 3px;
        height: 100%;
        background: linear-gradient(180deg, #3b82f6, #8b5cf6);
        opacity: 0;
        transition: opacity 0.3s ease;
    }

    .statistic-detail-item:hover {
        background: rgba(255, 255, 255, 0.05);
        border-color: rgba(59, 130, 246, 0.3);
        transform: translateY(-1px);
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    }

    .statistic-detail-item:hover::before {
        opacity: 1;
    }

    .statistic-detail-highlight {
        background: rgba(59, 130, 246, 0.08) !important;
        border-color: rgba(59, 130, 246, 0.2) !important;
    }

    .statistic-detail-highlight::before {
        opacity: 1 !important;
    }

    .statistic-detail-icon {
        font-size: 16px;
        margin-right: 8px;
        min-width: 20px;
        text-align: center;
        filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));
    }

    .statistic-detail-content {
        flex: 1;
        min-width: 0;
    }

    .statistic-detail-label {
        font-size: 10px;
        color: #94a3b8;
        text-transform: uppercase;
        letter-spacing: 0.5px;
        font-weight: 500;
        margin-bottom: 2px;
        line-height: 1;
    }

    .statistic-detail-value {
        font-size: 13px;
        color: #e2e8f0;
        font-weight: 600;
        line-height: 1.2;
        word-break: break-all;
    }

    .statistic-detail-value.profit-positive {
        color: #10b981;
    }

    .statistic-detail-value.profit-negative {
        color: #ef4444;
    }

    .statistic-detail-value.highlight {
        color: #60a5fa;
    }

    .statistic-detail-value.warning {
        color: #f59e0b;
    }


    /* 下载按钮样式 - 与其他数字保持一致 */
    .statistic-download-btn {
        color:rgb(243, 243, 243) !important;
        font-weight: normal !important;
        cursor: pointer !important;
        /* 继承其他数字的基础样式 */
    }

    .statistic-download-btn:hover {
        background-color: rgba(0, 255, 0, 0.1) !important;
        border-radius: 3px !important;
        transform: scale(1.03) !important;
    }

    .statistic-download-btn.disabled {
        color: rgba(135, 135, 135, 0.73) !important;
        cursor: not-allowed !important;
        pointer-events: none !important;
    }

    .statistic-download-btn.disabled:hover {
        background-color: transparent !important;
        transform: none !important;
    }

    /* 图片预览模态框样式 */
    .image-preview-modal {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.8);
        display: flex;
        justify-content: center;
        align-items: center;
        z-index: 10000;
        backdrop-filter: blur(5px);
    }

    .image-preview-content {
        background: #1a1a1a;
        border-radius: 12px;
        padding: 20px;
        max-width: 90vw;
        max-height: 90vh;
        display: flex;
        flex-direction: column;
        align-items: center;
        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
    }

    .image-preview-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        width: 100%;
        margin-bottom: 15px;
    }

    .image-preview-title {
        color: #ffffff;
        font-size: 18px;
        font-weight: bold;
    }

    .image-preview-close {
        background: none;
        border: none;
        color: #ffffff;
        font-size: 24px;
        cursor: pointer;
        padding: 5px;
        border-radius: 50%;
        width: 32px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: background 0.2s ease;
    }

    .image-preview-close:hover {
        background: rgba(255, 255, 255, 0.1);
    }

    .image-preview-img {
        max-width: 100%;
        max-height: 60vh;
        border-radius: 8px;
        margin-bottom: 20px;
        box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
    }

    .image-preview-buttons {
        display: flex;
        gap: 12px;
    }

    .image-preview-btn {
        padding: 10px 20px;
        border: none;
        border-radius: 6px;
        font-weight: bold;
        cursor: pointer;
        transition: all 0.2s ease;
        color: #ffffff;
    }

    .image-preview-btn.copy-btn {
        background: linear-gradient(135deg, #10b981, #059669);
    }

    .image-preview-btn.copy-btn:hover {
        background: linear-gradient(135deg, #059669, #047857);
        transform: translateY(-1px);
    }

    .image-preview-btn.download-btn {
        background: linear-gradient(135deg, #3b82f6, #1d4ed8);
    }

    .image-preview-btn.download-btn:hover {
        background: linear-gradient(135deg, #1d4ed8, #1e40af);
        transform: translateY(-1px);
    }

    /* 现代化提示框样式 */
    .modern-toast {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        z-index: 20000;
        background: rgba(0, 0, 0, 0.9);
        backdrop-filter: blur(10px);
        border-radius: 16px;
        padding: 0;
        box-shadow:
            0 20px 60px rgba(0, 0, 0, 0.6),
            0 8px 32px rgba(0, 0, 0, 0.4),
            inset 0 1px 0 rgba(255, 255, 255, 0.1);
        border: 1px solid rgba(255, 255, 255, 0.1);
        min-width: 300px;
        max-width: 400px;
        animation: toastSlideIn 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards;
        cursor: pointer;
    }

    .modern-toast-overlay {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: 19999;
        background: rgba(0, 0, 0, 0.3);
        backdrop-filter: blur(3px);
        animation: overlayFadeIn 0.3s ease forwards;
    }

    .modern-toast-content {
        display: flex;
        align-items: center;
        padding: 20px 24px;
        gap: 16px;
    }

    .modern-toast-icon {
        width: 48px;
        height: 48px;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 24px;
        flex-shrink: 0;
    }

    .modern-toast-icon.success {
        background: linear-gradient(135deg, #10b981, #059669);
        color: #ffffff;
    }

    .modern-toast-icon.error {
        background: linear-gradient(135deg, #ef4444, #dc2626);
        color: #ffffff;
    }

    .modern-toast-icon.info {
        background: linear-gradient(135deg, #3b82f6, #1d4ed8);
        color: #ffffff;
    }

    .modern-toast-text {
        flex: 1;
        color: #ffffff;
        font-size: 16px;
        font-weight: 500;
        line-height: 1.4;
    }

    .modern-toast-close {
        width: 32px;
        height: 32px;
        border-radius: 50%;
        background: rgba(255, 255, 255, 0.1);
        border: none;
        color: #ffffff;
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 18px;
        transition: all 0.2s ease;
        flex-shrink: 0;
    }

    .modern-toast-close:hover {
        background: rgba(255, 255, 255, 0.2);
        transform: scale(1.1);
    }

    @keyframes toastSlideIn {
        from {
            opacity: 0;
            transform: translate(-50%, -50%) scale(0.8) rotateY(-10deg);
        }
        to {
            opacity: 1;
            transform: translate(-50%, -50%) scale(1) rotateY(0deg);
        }
    }

    @keyframes overlayFadeIn {
        from {
            opacity: 0;
        }
        to {
            opacity: 1;
        }
    }

    @keyframes toastSlideOut {
        from {
            opacity: 1;
            transform: translate(-50%, -50%) scale(1) rotateY(0deg);
        }
        to {
            opacity: 0;
            transform: translate(-50%, -50%) scale(0.8) rotateY(10deg);
        }
    }
`;
    document.head.appendChild(style);

    // 存储拦截到的数据
    let interceptedData = null;
    // 存储首次加载的数据
    let initialStats = null;
    // 标记是否是首次加载
    let isFirstLoad = true;
    // 新增存储当前CA地址
    let currentCaAddress = null;
    // 存储首次加载的CA地址
    let initialCaAddress = null;

    // 检查当前网络是否为SOL
    function isSolNetwork() {
        const url = window.location.href;
        return url.includes('/sol/') || url.includes('gmgn.ai/sol');
    }

    // 获取可疑地址的具体类型标识
    function getSuspiciousTypeLabels(holder) {
        const labels = [];

        // 基础可疑标记
        if (holder.is_suspicious) {
            labels.push({
                text: '可疑',
                color: '#dc2626',
                bgColor: 'rgba(220, 38, 38, 0.15)',
                borderColor: 'rgba(220, 38, 38, 0.3)'
            });
        }

        // 检查maker_token_tags
        if (holder.maker_token_tags) {
            if (holder.maker_token_tags.includes('rat_trader')) {
                labels.push({
                    text: '老鼠仓',
                    color: '#ef4444',
                    bgColor: 'rgba(239, 68, 68, 0.15)',
                    borderColor: 'rgba(239, 68, 68, 0.3)'
                });
            }

            if (holder.transfer_in) {
                labels.push({
                    text: '小鱼钱包',
                    color: '#f87171',
                    bgColor: 'rgba(248, 113, 113, 0.15)',
                    borderColor: 'rgba(248, 113, 113, 0.3)'
                });
            }

            if (holder.maker_token_tags.includes('bundler')) {
                labels.push({
                    text: '捆绑交易',
                    color: '#b91c1c',
                    bgColor: 'rgba(185, 28, 28, 0.15)',
                    borderColor: 'rgba(185, 28, 28, 0.3)'
                });
            }
        }

        return labels;
    }

    // 生成现代化详情数据HTML
    function generateDetailItemHTML(icon, label, value, valueClass = '', isHighlight = false) {
        const highlightClass = isHighlight ? 'statistic-detail-highlight' : '';
        return `
            <div class="statistic-detail-item ${highlightClass}">
                <div class="statistic-detail-icon">${icon}</div>
                <div class="statistic-detail-content">
                    <div class="statistic-detail-label">${label}</div>
                    <div class="statistic-detail-value ${valueClass}">${value}</div>
                </div>
            </div>
        `;
    }

    // 生成可疑标识HTML
    function generateSuspiciousLabelsHTML(labels) {
        if (!labels || labels.length === 0) {
            return '';
        }

        const labelsHTML = labels.map(label => {
            const typeClass = label.text === '老鼠仓' ? 'rat-trader' :
                             label.text === '小鱼钱包' ? 'transfer-in' :
                             label.text === '捆绑交易' ? 'bundler' : '';

            return `<span class="statistic-suspicious-label ${typeClass}"
                          style="color: ${label.color};
                                 background: ${label.bgColor};
                                 border-color: ${label.borderColor};"
                          title="${label.text}标识">
                        ${label.text}
                    </span>`;
        }).join('');

        return `<div class="statistic-suspicious-labels">${labelsHTML}</div>`;
    }

    // 检查是否为交易所地址
    function isExchangeAddress(holder) {
        const exchangeNames = ['coinbase', 'binance', 'bybit', 'bitget', 'okx', 'kraken', 'coinsquare', 'crypto.com', 'robinhood', 'mexc'];

        // 检查native_transfer中的name
        if (holder.native_transfer && holder.native_transfer.name) {
            const name = holder.native_transfer.name.toLowerCase();
            if (exchangeNames.some(exchange => name.includes(exchange))) {
                return true;
            }
        }

        // 检查其他可能的transfer字段
        if (holder.transfer && holder.transfer.name) {
            const name = holder.transfer.name.toLowerCase();
            if (exchangeNames.some(exchange => name.includes(exchange))) {
                return true;
            }
        }

        return false;
    }

    // 获取交易所名称
    function getExchangeName(holder) {
        const exchangeNames = ['coinbase', 'binance', 'bybit', 'bitget', 'okx', 'kraken', 'coinsquare', 'crypto.com', 'robinhood', 'mexc'];

        let sourceName = '';
        if (holder.native_transfer && holder.native_transfer.name) {
            sourceName = holder.native_transfer.name.toLowerCase();
        } else if (holder.transfer && holder.transfer.name) {
            sourceName = holder.transfer.name.toLowerCase();
        }

        for (let exchange of exchangeNames) {
            if (sourceName.includes(exchange)) {
                return exchange.charAt(0).toUpperCase() + exchange.slice(1);
            }
        }

        return 'Unknown';
    }
    // 交易所专用弹框
    function createExchangeModal(data, caAddress) {
        // 移除已存在的弹框
        const existingModal = document.querySelector('.statistic-gmgn-modal');
        if (existingModal) {
            existingModal.remove();
        }

        // 按交易所分组数据
        const exchangeGroups = {};
        data.forEach(holder => {
            const exchangeName = getExchangeName(holder);
            if (!exchangeGroups[exchangeName]) {
                exchangeGroups[exchangeName] = [];
            }
            exchangeGroups[exchangeName].push(holder);
        });

        // 计算已卖筹码地址数
        const soldAddressCount = data.filter(holder => (holder.sell_amount_percentage || 0) > 0).length;

        // 计算总持仓占比
        const totalHoldingPercentage = data.reduce((sum, holder) => {
            return sum + (holder.amount_percentage || 0);
        }, 0);

        // 创建弹框
        const modal = document.createElement('div');
        modal.className = 'statistic-gmgn-modal';

        // 生成交易所统计数据
        const exchangeSummary = Object.keys(exchangeGroups).map(exchange => {
            return {
                name: exchange,
                count: exchangeGroups[exchange].length,
                addresses: exchangeGroups[exchange]
            };
        }).sort((a, b) => b.count - a.count);

        modal.innerHTML = `
            <div class="statistic-gmgn-modal-content">
                <div class="statistic-gmgn-modal-header">
                    <div class="statistic-gmgn-modal-title">🚀 交易所地址分析 (共${data.length}个地址)</div>
                    <button class="statistic-gmgn-modal-close">&times;</button>
                </div>
                <div class="statistic-gmgn-analysis-summary">
                    <div class="statistic-gmgn-summary-stats">
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">已卖筹码地址数:</span>
                            <span class="statistic-gmgn-stat-value">${soldAddressCount}</span>
                        </div>
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">交易所数:</span>
                            <span class="statistic-gmgn-stat-value">${Object.keys(exchangeGroups).length}</span>
                        </div>
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">总持仓占比:</span>
                            <span class="statistic-gmgn-stat-value">${(totalHoldingPercentage * 100).toFixed(2)}%</span>
                        </div>
                    </div>
                    <button id="statistic-export-exchange-btn" class="statistic-gmgn-export-btn" title="导出Excel">导出Excel</button>
                </div>
                <div id="statistic-exchange-summary">
                    <div class="statistic-gmgn-section-title">📱 交易所统计</div>
                    <div class="statistic-exchange-summary-grid">
                        ${exchangeSummary.map(item => `
                            <div class="statistic-exchange-summary-item" data-exchange="${item.name}">
                                <span class="statistic-exchange-name">${item.name}</span>
                                <span class="statistic-exchange-count">${item.count}个地址</span>
                            </div>
                        `).join('')}
                    </div>
                </div>
                <div id="statistic-exchange-details"></div>
            </div>
        `;

        document.body.appendChild(modal);

        // 添加交易所统计样式
        if (!document.getElementById('exchange-summary-styles')) {
            const summaryStyles = document.createElement('style');
            summaryStyles.id = 'exchange-summary-styles';
            summaryStyles.textContent = `
                .statistic-exchange-summary-grid {
                    display: grid;
                    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                    gap: 12px;
                    margin-bottom: 20px;
                }
                .statistic-exchange-summary-item {
                    background-color: #475569;
                    border-radius: 8px;
                    padding: 12px 16px;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    cursor: pointer;
                    transition: all 0.3s ease;
                    border: 2px solid transparent;
                }
                .statistic-exchange-summary-item:hover {
                    background-color: #64748b;
                    border-color: #3b82f6;
                    transform: translateY(-2px);
                }
                .statistic-exchange-summary-item.active {
                    background-color: #3b82f6;
                    border-color: #1d4ed8;
                }
                .statistic-exchange-name {
                    font-weight: 600;
                    color: #e2e8f0;
                    font-size: 14px;
                }
                .statistic-exchange-count {
                    color: #10b981;
                    font-weight: 600;
                    font-size: 13px;
                }
                .statistic-exchange-details-section {
                    margin-bottom: 20px;
                }
                .statistic-exchange-section-header {
                    background-color: #1e293b;
                    padding: 12px 16px;
                    border-radius: 8px 8px 0 0;
                    border-left: 4px solid #3b82f6;
                    margin-bottom: 0;
                }
                .statistic-exchange-section-title {
                    font-size: 16px;
                    font-weight: 600;
                    color: #3b82f6;
                    margin: 0;
                }
                .statistic-exchange-section-count {
                    font-size: 12px;
                    color: #94a3b8;
                    margin-top: 4px;
                }
            `;
            document.head.appendChild(summaryStyles);
        }

        // 绑定交易所统计点击事件
        exchangeSummary.forEach(item => {
            const summaryItem = modal.querySelector(`[data-exchange="${item.name}"]`);
            if (summaryItem) {
                summaryItem.addEventListener('click', () => {
                    // 移除所有活跃状态
                    modal.querySelectorAll('.statistic-exchange-summary-item').forEach(el => {
                        el.classList.remove('active');
                    });
                    // 添加当前活跃状态
                    summaryItem.classList.add('active');
                    // 显示该交易所的详细信息
                    displayExchangeDetails(item.addresses, item.name, modal);
                });
            }
        });

        // ESC键关闭处理函数
        const escKeyHandler = (e) => {
            if (e.key === 'Escape') {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        };
        document.addEventListener('keydown', escKeyHandler);

        // 绑定导出Excel按钮事件
        const exportBtn = modal.querySelector('#statistic-export-exchange-btn');
        if (exportBtn) {
            exportBtn.addEventListener('click', () => {
                exportExchangeToExcel(exchangeGroups, caAddress);
            });
        }

        // 绑定关闭按钮事件
        modal.querySelector('.statistic-gmgn-modal-close').addEventListener('click', () => {
            document.body.removeChild(modal);
            document.removeEventListener('keydown', escKeyHandler);
        });

        // 点击模态框外部关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        });

        // 默认显示第一个交易所的详情
        if (exchangeSummary.length > 0) {
            const firstItem = modal.querySelector(`[data-exchange="${exchangeSummary[0].name}"]`);
            if (firstItem) {
                firstItem.click();
            }
        }
    }

    // 显示交易所详细信息
    function displayExchangeDetails(addresses, exchangeName, modal) {
        const detailsContainer = modal.querySelector('#statistic-exchange-details');

        // 创建全局排名映射 - 基于原始完整数据按持仓比例排序
        const globalRankMap = new Map();
        if (interceptedData?.data?.list) {
            const allHolders = [...interceptedData.data.list];
            allHolders
                .sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0))
                .forEach((holder, index) => {
                    globalRankMap.set(holder.address, index + 1);
                });
        }

        // 按持仓比例排序
        const sortedAddresses = addresses.sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0));

        detailsContainer.innerHTML = `
            <div class="statistic-exchange-details-section">
                <div class="statistic-exchange-section-header">
                    <div class="statistic-exchange-section-title">${exchangeName} 地址详情</div>
                    <div class="statistic-exchange-section-count">共 ${sortedAddresses.length} 个地址</div>
                </div>
                ${sortedAddresses.map((holder, index) => {
                    const globalRank = globalRankMap.get(holder.address) || (index + 1);
                    const processedData = {
                        rank: index + 1,
                        rankIndex: globalRank, // 使用全局排名
                        address: holder.address,
                        balance: formatNumber(holder.balance),
                        usdValue: formatNumber(holder.usd_value),
                        netflowUsd: formatNumber(holder.netflow_usd),
                        netflowClass: (holder.netflow_usd || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                        profit: formatNumber(holder.profit),
                        profitSign: holder.profit >= 0 ? '+' : '',
                        profitClass: holder.profit >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                        profitChange: holder.profit_change ? (holder.profit_change * 100).toFixed(1) + '%' : 'N/A',
                        profitChangeClass: (holder.profit_change || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                        exchangeName: getExchangeName(holder),
                        transferName: (holder.native_transfer && holder.native_transfer.name) || (holder.transfer && holder.transfer.name) || 'N/A',
                        amountPercentage: holder.amount_percentage ? (holder.amount_percentage * 100).toFixed(2) + '%' : 'N/A',
                        sellPercentage: holder.sell_amount_percentage ? (holder.sell_amount_percentage * 100).toFixed(2) + '%' : '0.00%' // 筹码已卖
                    };

                    return `
                        <div class="statistic-gmgn-result-item">
                            <div class="statistic-gmgn-result-header">
                                <div class="statistic-gmgn-result-rank">
                                    <span style="color: #ff6b35; font-weight: bold; background: rgba(255, 107, 53, 0.15); padding: 2px 6px; border-radius: 12px; border: 1px solid rgba(255, 107, 53, 0.3); font-size: 12px;">榜${processedData.rankIndex}</span>
                                </div>
                                <div class="statistic-gmgn-result-address" title="点击复制地址" onclick="navigator.clipboard.writeText('${processedData.address}'); this.style.backgroundColor='#16a34a'; this.style.color='white'; setTimeout(() => { this.style.backgroundColor=''; this.style.color=''; }, 1000);">${processedData.address}</div>
                                <a href="https://gmgn.ai/sol/address/${processedData.address}" target="_blank" class="statistic-gmgn-address-jump-btn" title="查看钱包详情">详情</a>
                            </div>
                            <div class="statistic-gmgn-compact-details">
                                <div class="statistic-gmgn-detail-section">
                                    <div class="statistic-gmgn-section-title">基本信息</div>
                                    <div class="statistic-detail-grid-modern">
                                        ${generateDetailItemHTML('💎', '持仓', processedData.balance)}
                                        ${generateDetailItemHTML('✨', '持仓占比', processedData.amountPercentage, 'highlight', true)}
                                        ${generateDetailItemHTML('📉', '筹码已卖', processedData.sellPercentage, processedData.sellPercentage === '0.00%' ? 'profit-positive' : 'warning')}
                                        ${generateDetailItemHTML('💰', '净流入', '$' + processedData.netflowUsd, processedData.netflowClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                                        ${generateDetailItemHTML('📈', '盈亏', processedData.profitSign + '$' + processedData.profit, processedData.profitClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                                        ${generateDetailItemHTML('🚀', '倍数', processedData.profitChange, processedData.profitChangeClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                                        ${generateDetailItemHTML('🏢', '交易所', processedData.exchangeName, 'highlight', true)}
                                        ${generateDetailItemHTML('🏷️', '标签', processedData.transferName)}
                                    </div>
                                </div>
                            </div>
                        </div>
                    `;
                }).join('')}
            </div>
        `;
    }

    // 交易所数据导出函数
    function exportExchangeToExcel(exchangeGroups, caAddress) {
        try {
            const worksheetData = [];

            // 添加标题行
            worksheetData.push(['交易所', '排名', '地址', '持仓数量', '持仓比例', '筹码已卖', 'USD价值', '净流入USD', '盈亏USD', '盈亏倍数', '标签名称']);

            // 按交易所排序添加数据
            Object.keys(exchangeGroups).forEach(exchangeName => {
                const addresses = exchangeGroups[exchangeName].sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0));
                addresses.forEach((holder, index) => {
                    const row = [
                        exchangeName,
                        index + 1,
                        holder.address,
                        formatNumber(holder.balance),
                        holder.amount_percentage ? (holder.amount_percentage * 100).toFixed(2) + '%' : 'N/A',
                        holder.sell_amount_percentage ? (holder.sell_amount_percentage * 100).toFixed(2) + '%' : '0.00%',
                        formatNumber(holder.usd_value),
                        formatNumber(holder.netflow_usd),
                        (holder.profit >= 0 ? '+' : '') + formatNumber(holder.profit),
                        holder.profit_change ? (holder.profit_change * 100).toFixed(1) + '%' : 'N/A',
                        (holder.native_transfer && holder.native_transfer.name) || (holder.transfer && holder.transfer.name) || 'N/A'
                    ];
                    worksheetData.push(row);
                });
            });

            // 创建工作簿
            const wb = XLSX.utils.book_new();
            const ws = XLSX.utils.aoa_to_sheet(worksheetData);

            // 设置列宽
            const colWidths = [
                {wch: 12},  // 交易所
                {wch: 6},   // 排名
                {wch: 45},  // 地址
                {wch: 15},  // 持仓数量
                {wch: 10},  // 持仓比例
                {wch: 10},  // 已卖比例
                {wch: 15},  // USD价值
                {wch: 15},  // 净流入
                {wch: 15},  // 盈亏
                {wch: 12},  // 倍数
                {wch: 25}   // 标签名称
            ];
            ws['!cols'] = colWidths;

            // 添加工作表到工作簿
            XLSX.utils.book_append_sheet(wb, ws, '交易所地址');

            // 生成文件名
            const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
            const fileName = `交易所地址_${caAddress ? caAddress.slice(0, 8) : 'data'}_${timestamp}.xlsx`;

            // 下载文件
            XLSX.writeFile(wb, fileName);

            // 显示成功提示
            const exportBtn = document.querySelector('#statistic-export-exchange-btn');
            if (exportBtn) {
                const originalText = exportBtn.textContent;
                exportBtn.textContent = '✅ 导出成功';
                exportBtn.style.backgroundColor = '#059669';
                setTimeout(() => {
                    exportBtn.textContent = originalText;
                    exportBtn.style.backgroundColor = '';
                }, 2000);
            }

        } catch (error) {
            console.error('Excel导出失败:', error);
            showModernToast('导出失败,请检查浏览器控制台了解详情', 'error');
        }
    }

    // 优化后的弹框管理函数 - 添加分页支持
    function createModal(title, data, caAddress, showSolBalance = false) {
        // 移除已存在的弹框
        const existingModal = document.querySelector('.statistic-gmgn-modal');
        if (existingModal) {
            existingModal.remove();
        }

        // 性能优化:数据量限制
        const ITEMS_PER_PAGE = 50;
        const isLargeDataset = data.length > ITEMS_PER_PAGE;
        let currentPage = 1;
        let totalPages = Math.ceil(data.length / ITEMS_PER_PAGE);

        // 1. 数据预处理 - 首先获取全局排名
        if (!interceptedData?.data?.list) {
            console.error('无法获取原始数据进行全局排名');
            return;
        }

        // 创建全局排名映射 - 基于原始完整数据按持仓比例排序
        const globalRankMap = new Map();
        const allHolders = [...interceptedData.data.list];
        allHolders
            .sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0))
            .forEach((holder, index) => {
                globalRankMap.set(holder.address, index + 1);
            });

        // 2. 计算已卖筹码地址数
        const soldAddressCount = data.filter(holder => (holder.sell_amount_percentage || 0) > 0).length;

        // 计算总持仓占比
        const totalHoldingPercentage = data.reduce((sum, holder) => {
            return sum + (holder.amount_percentage || 0);
        }, 0);

        // 3. 处理所有数据并排序
        const allProcessedData = data
            .sort((a, b) => (b.amount_percentage || 0) - (a.amount_percentage || 0)) // 按持仓比例排序
            .map((holder, index) => {
                const globalRank = globalRankMap.get(holder.address) || (index + 1);
                const baseData = {
                    rank: index + 1, // 在当前数据集中的排名(用于显示序号)
                    rankIndex: globalRank, // 在全局数据中的排名(用于显示"榜X")
                    address: holder.address,
                    balance: formatNumber(holder.balance),
                    usdValue: formatNumber(holder.usd_value),
                    netflowUsd: formatNumber(holder.netflow_usd),
                    netflowClass: (holder.netflow_usd || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                    profit: formatNumber(holder.profit),
                    profitSign: holder.profit >= 0 ? '+' : '',
                    profitClass: holder.profit >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                    profitChange: holder.profit_change ? (holder.profit_change * 100).toFixed(1) + '%' : 'N/A',
                    profitChangeClass: (holder.profit_change || 0) >= 0 ? 'statistic-gmgn-profit-positive' : 'statistic-gmgn-profit-negative',
                    amountPercentage: holder.amount_percentage ? (holder.amount_percentage * 100).toFixed(2) + '%' : 'N/A',
                    sellPercentage: holder.sell_amount_percentage ? (holder.sell_amount_percentage * 100).toFixed(2) + '%' : '0.00%', // 筹码已卖
                    // 添加可疑类型标识
                    suspiciousLabels: getSuspiciousTypeLabels(holder),
                    // 保留原始数据用于检测
                    originalHolder: holder
                };

                // 只有在需要显示SOL余额时才添加
                if (showSolBalance) {
                    baseData.solBalance = holder.native_balance ? ((holder.native_balance / 1000000000).toFixed(2) + ' SOL') : 'N/A';
                }

                return baseData;
            });

        // 分页处理:获取当前页数据
        function getCurrentPageData(page = 1) {
            const start = (page - 1) * ITEMS_PER_PAGE;
            const end = start + ITEMS_PER_PAGE;
            return allProcessedData.slice(start, end);
        }

        const processedData = getCurrentPageData(currentPage);

        // 2. 创建弹框基础结构 - 使用token_holding_temp.js的DOM结构
        const modal = document.createElement('div');
        modal.className = 'statistic-gmgn-modal';
        modal.innerHTML = `
            <div class="statistic-gmgn-modal-content">
                <div class="statistic-gmgn-modal-header">
                    <div class="statistic-gmgn-modal-title">💎 ${title} (${allProcessedData.length}个地址)</div>
                    <button class="statistic-gmgn-modal-close">&times;</button>
                </div>
                ${isLargeDataset ? `
                <div class="statistic-gmgn-pagination-info">
                    <span class="statistic-pagination-text">⚡ 性能优化:分页显示 | 第${currentPage}页,共${totalPages}页 | 每页${ITEMS_PER_PAGE}条</span>
                </div>
                ` : ''}
                <div class="statistic-gmgn-analysis-summary">
                    <div class="statistic-gmgn-summary-stats">
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">已卖筹码地址数:</span>
                            <span class="statistic-gmgn-stat-value">${soldAddressCount}</span>
                        </div>
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">总数量:</span>
                            <span class="statistic-gmgn-stat-value">${allProcessedData.length}</span>
                        </div>
                        <div class="statistic-gmgn-stat-item">
                            <span class="statistic-gmgn-stat-label">总持仓占比:</span>
                            <span class="statistic-gmgn-stat-value">${(totalHoldingPercentage * 100).toFixed(2)}%</span>
                        </div>
                    </div>
                    <button id="statistic-export-excel-btn" class="statistic-gmgn-export-btn" title="导出Excel">导出Excel</button>
                </div>
                <div id="statistic-gmgn-results-list"></div>
                ${isLargeDataset ? `
                <div class="statistic-gmgn-pagination-controls">
                    <button id="statistic-prev-page" class="statistic-pagination-btn" ${currentPage === 1 ? 'disabled' : ''}>← 上一页</button>
                    <span class="statistic-pagination-current">第 ${currentPage} 页 / 共 ${totalPages} 页</span>
                    <button id="statistic-next-page" class="statistic-pagination-btn" ${currentPage === totalPages ? 'disabled' : ''}>下一页 →</button>
                </div>
                ` : ''}
                </div>
        `;

        // 3. 插入DOM
        document.body.appendChild(modal);

        // 4. 填充结果列表 - 参考token_holding_temp.js的方式
        const resultsList = document.getElementById('statistic-gmgn-results-list');
        processedData.forEach((holder, index) => {
            const item = document.createElement('div');
            item.className = 'statistic-gmgn-result-item';
            item.innerHTML = `
                <div class="statistic-gmgn-result-header">
                    <div class="statistic-gmgn-result-rank">
                        <span style="color: #ff6b35; font-weight: bold; background: rgba(255, 107, 53, 0.15); padding: 2px 6px; border-radius: 12px; border: 1px solid rgba(255, 107, 53, 0.3); font-size: 12px;">榜${holder.rankIndex}</span>
                    </div>
                    <div class="statistic-gmgn-result-address" title="点击复制地址">${holder.address}</div>
                    <a href="https://gmgn.ai/sol/address/${holder.address}" target="_blank" class="statistic-gmgn-address-jump-btn" title="查看钱包详情">详情</a>
                </div>
                <div class="statistic-gmgn-compact-details">
                    <div class="statistic-gmgn-detail-section">
                        <div class="statistic-gmgn-section-title">
                            基本信息
                            ${generateSuspiciousLabelsHTML(holder.suspiciousLabels)}
                        </div>
                        <div class="statistic-detail-grid-modern">
                            ${generateDetailItemHTML('💎', '持仓', holder.balance)}
                            ${generateDetailItemHTML('✨', '持仓占比', holder.amountPercentage, 'highlight', true)}
                            ${generateDetailItemHTML('📉', '筹码已卖', holder.sellPercentage, holder.sellPercentage === '0.00%' ? 'profit-positive' : 'warning')}
                            ${generateDetailItemHTML('💰', '净流入', '$' + holder.netflowUsd, holder.netflowClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                            ${generateDetailItemHTML('📈', '盈亏', holder.profitSign + '$' + holder.profit, holder.profitClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                            ${generateDetailItemHTML('🚀', '倍数', holder.profitChange, holder.profitChangeClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                            ${holder.solBalance ? generateDetailItemHTML('⭐', 'SOL餘額', holder.solBalance, 'highlight') : ''}
                            </div>
                </div>
            </div>
        `;

            // 添加地址复制功能
            const addressElement = item.querySelector('.statistic-gmgn-result-address');
            addressElement.addEventListener('click', () => {
                navigator.clipboard.writeText(holder.address).then(() => {
                    addressElement.style.backgroundColor = '#16a34a';
                    addressElement.style.color = 'white';
                    setTimeout(() => {
                        addressElement.style.backgroundColor = '';
                        addressElement.style.color = '';
                    }, 1000);
                });
            });

            resultsList.appendChild(item);
        });

        // ESC键关闭处理函数
        const escKeyHandler = (e) => {
            if (e.key === 'Escape') {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        };
        document.addEventListener('keydown', escKeyHandler);

        // 5. 绑定导出Excel按钮事件 - 导出完整数据而非分页数据
        const exportBtn = modal.querySelector('#statistic-export-excel-btn');
        if (exportBtn) {
            exportBtn.addEventListener('click', () => {
                exportToExcel(allProcessedData, title, caAddress, showSolBalance);
            });
        }

        // 6. 分页控制逻辑
        if (isLargeDataset) {
            // 渲染指定页面的数据
            function renderPage(page) {
                currentPage = page;
                const currentPageData = getCurrentPageData(page);

                // 清空当前列表
                const resultsList = document.getElementById('statistic-gmgn-results-list');
                resultsList.innerHTML = '';

                // 重新渲染当前页数据
                currentPageData.forEach((holder, index) => {
                    const item = document.createElement('div');
                    item.className = 'statistic-gmgn-result-item';
                    item.innerHTML = `
                        <div class="statistic-gmgn-result-header">
                            <div class="statistic-gmgn-result-rank">
                                <span style="color: #ff6b35; font-weight: bold; background: rgba(255, 107, 53, 0.15); padding: 2px 6px; border-radius: 12px; border: 1px solid rgba(255, 107, 53, 0.3); font-size: 12px;">榜${holder.rankIndex}</span>
                            </div>
                            <div class="statistic-gmgn-result-address" title="点击复制地址">${holder.address}</div>
                            <a href="https://gmgn.ai/sol/address/${holder.address}" target="_blank" class="statistic-gmgn-address-jump-btn" title="查看钱包详情">详情</a>
                        </div>
                        <div class="statistic-gmgn-compact-details">
                            <div class="statistic-gmgn-detail-section">
                                <div class="statistic-gmgn-section-title">
                                    基本信息
                                    ${generateSuspiciousLabelsHTML(holder.suspiciousLabels)}
                                </div>
                                <div class="statistic-detail-grid-modern">
                                    ${generateDetailItemHTML('💎', '持仓', holder.balance)}
                                    ${generateDetailItemHTML('✨', '持仓占比', holder.amountPercentage, 'highlight', true)}
                                    ${generateDetailItemHTML('📉', '筹码已卖', holder.sellPercentage, holder.sellPercentage === '0.00%' ? 'profit-positive' : 'warning')}
                                    ${generateDetailItemHTML('💰', '净流入', '$' + holder.netflowUsd, holder.netflowClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                                    ${generateDetailItemHTML('📈', '盈亏', holder.profitSign + '$' + holder.profit, holder.profitClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                                    ${generateDetailItemHTML('🚀', '倍数', holder.profitChange, holder.profitChangeClass.includes('positive') ? 'profit-positive' : 'profit-negative')}
                                    ${holder.solBalance ? generateDetailItemHTML('⭐', 'SOL餘額', holder.solBalance, 'highlight') : ''}
                                </div>
                            </div>
                        </div>
                    `;

                    // 添加地址复制功能
                    const addressElement = item.querySelector('.statistic-gmgn-result-address');
                    addressElement.addEventListener('click', () => {
                        navigator.clipboard.writeText(holder.address).then(() => {
                            addressElement.style.backgroundColor = '#16a34a';
                            addressElement.style.color = 'white';
                            setTimeout(() => {
                                addressElement.style.backgroundColor = '';
                                addressElement.style.color = '';
                            }, 1000);
                        });
                    });

                    resultsList.appendChild(item);
                });

                // 更新分页按钮状态
                const prevBtn = modal.querySelector('#statistic-prev-page');
                const nextBtn = modal.querySelector('#statistic-next-page');
                const currentSpan = modal.querySelector('.statistic-pagination-current');

                if (prevBtn) {
                    prevBtn.disabled = (page === 1);
                }
                if (nextBtn) {
                    nextBtn.disabled = (page === totalPages);
                }
                if (currentSpan) {
                    currentSpan.textContent = `第 ${page} 页 / 共 ${totalPages} 页`;
                }
            }

            // 绑定分页按钮事件
            const prevBtn = modal.querySelector('#statistic-prev-page');
            const nextBtn = modal.querySelector('#statistic-next-page');

            if (prevBtn) {
                prevBtn.addEventListener('click', () => {
                    if (currentPage > 1) {
                        renderPage(currentPage - 1);
                    }
                });
            }

            if (nextBtn) {
                nextBtn.addEventListener('click', () => {
                    if (currentPage < totalPages) {
                        renderPage(currentPage + 1);
                    }
                });
            }
        }

        // 7. 绑定关闭按钮事件
        modal.querySelector('.statistic-gmgn-modal-close').addEventListener('click', () => {
            document.body.removeChild(modal);
            document.removeEventListener('keydown', escKeyHandler);
        });

        // 点击模态框外部关闭
        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                document.body.removeChild(modal);
                document.removeEventListener('keydown', escKeyHandler);
            }
        });
    }





    // 数字格式化函数
    function formatNumber(num) {
        if (num === null || num === undefined) return 'N/A';

        // 處理負數:保留負號,對絕對值進行格式化
        const isNegative = num < 0;
        const absNum = Math.abs(num);

        let formatted;
        if (absNum >= 1000000000) {
            formatted = (absNum / 1000000000).toFixed(2) + 'B';
        } else if (absNum >= 1000000) {
            formatted = (absNum / 1000000).toFixed(2) + 'M';
        } else if (absNum >= 1000) {
            formatted = (absNum / 1000).toFixed(2) + 'K';
        } else {
            formatted = absNum.toFixed(2);
        }

        return isNegative ? '-' + formatted : formatted;
    }

    // Excel导出功能
    function exportToExcel(data, title, caAddress, showSolBalance) {
        try {
            // 创建工作表数据
            const worksheetData = [];

            // 添加标题行
            const headers = ['排名', '地址', '持仓数量', '持仓占比', '筹码已卖', 'USD价值', '净流入USD', '盈亏USD', '盈亏倍数'];
            if (showSolBalance) {
                headers.push('SOL餘額');
            }
            worksheetData.push(headers);

            // 添加数据行
            data.forEach((holder, index) => {
                const row = [
                    holder.rank,
                    holder.address,
                    holder.balance,
                    holder.amountPercentage,
                    holder.sellPercentage,
                    holder.usdValue,
                    holder.netflowUsd,
                    (holder.profitSign || '') + holder.profit,
                    holder.profitChange
                ];

                if (showSolBalance) {
                    row.push(holder.solBalance || 'N/A');
                }

                worksheetData.push(row);
            });

            // 创建工作簿
            const wb = XLSX.utils.book_new();
            const ws = XLSX.utils.aoa_to_sheet(worksheetData);

            // 设置列宽
            const colWidths = [
                {wch: 6},   // 排名
                {wch: 45},  // 地址
                {wch: 15},  // 持仓数量
                {wch: 10},  // 持仓比例
                {wch: 10},  // 已卖比例
                {wch: 15},  // USD价值
                {wch: 15},  // 净流入
                {wch: 15},  // 盈亏
                {wch: 12}   // 倍数
            ];
            if (showSolBalance) {
                colWidths.push({wch: 12}); // SOL餘額
            }
            ws['!cols'] = colWidths;

            // 添加工作表到工作簿
            XLSX.utils.book_append_sheet(wb, ws, title);

            // 生成文件名
            const timestamp = new Date().toISOString().slice(0, 19).replace(/:/g, '-');
            const fileName = `${title}_${caAddress ? caAddress.slice(0, 8) : 'data'}_${timestamp}.xlsx`;

            // 下载文件
            XLSX.writeFile(wb, fileName);

            // 显示成功提示
            const exportBtn = document.querySelector('#statistic-export-excel-btn');
            if (exportBtn) {
                const originalText = exportBtn.textContent;
                exportBtn.textContent = '✅ 导出成功';
                exportBtn.style.backgroundColor = '#059669';
                setTimeout(() => {
                    exportBtn.textContent = originalText;
                    exportBtn.style.backgroundColor = '';
                }, 2000);
            }

        } catch (error) {
            console.error('Excel导出失败:', error);
            showModernToast('导出失败,请检查浏览器控制台了解详情', 'error');
        }
    }

    // 根据类型获取对应的地址数据
    function getAddressByType(type) {
        if (!interceptedData?.data?.list) return [];

        const currentTime = Math.floor(Date.now() / 1000);
        const sevenDaysInSeconds = 7 * 24 * 60 * 60;
        const holders = interceptedData.data.list;

        switch(type) {
            case 'fullPosition':
                return holders.filter(h =>
                    h.sell_amount_percentage === 0 &&
                    (!h.token_transfer_out || !h.token_transfer_out.address)
                );
            case 'profitable':
                return holders.filter(h => h.profit > 0);
            case 'losing':
                return holders.filter(h => h.profit < 0);
            case 'active24h':
                return holders.filter(h => h.last_active_timestamp > currentTime - 86400);
            case 'diamondHands':
                return holders.filter(h => h.maker_token_tags?.includes('diamond_hands'));
            case 'newAddress':
                return holders.filter(h => h.tags?.includes('fresh_wallet'));
            case 'holdingLessThan7Days':
                return holders.filter(h =>
                    h.start_holding_at &&
                    (currentTime - h.start_holding_at) < sevenDaysInSeconds
                );
            case 'highProfit':
                return holders.filter(h => h.profit_change > 5);
            case 'suspicious':
                return holders.filter(h =>
                    h.is_suspicious ||
                    h.transfer_in ||
                    (h.maker_token_tags && (
                        h.maker_token_tags.includes('rat_trader') ||
                        h.maker_token_tags.includes('bundler')
                    ))
                );
            case 'lowSolBalance':
                return holders.filter(h =>
                    h.native_balance && (h.native_balance / 1000000000) < 1
                );
            case 'tokenTransferIn':
                return holders.filter(h =>
                    h.token_transfer_in && h.token_transfer_in.address && h.token_transfer_in.address.trim() !== ''
                );
            case 'exchangeAddresses':
                return holders.filter(h => isExchangeAddress(h));
            default:
                return [];
        }
    }

    // 获取类型对应的中文标题
    function getTypeTitle(type) {
        const titles = {
            'fullPosition': '满仓地址',
            'profitable': '盈利地址',
            'losing': '亏损地址',
            'active24h': '24小时活跃地址',
            'diamondHands': '钻石手地址',
            'newAddress': '新地址',
            'holdingLessThan7Days': '持仓小于7天的地址',
            'highProfit': '5倍以上盈利地址',
            'suspicious': '可疑地址',
            'lowSolBalance': 'SOL餘額不足1的地址',
            'tokenTransferIn': '代币转入地址',
            'exchangeAddresses': '交易所地址'
        };
        return titles[type] || '未知类型';
    }

    // 1. 拦截 fetch 请求
    const originalFetch = window.fetch;
    window.fetch = function(url, options) {
        if (isTargetApi(url)) {
            console.log('[拦截] fetch 请求:', url);
            return originalFetch.apply(this, arguments)
                .then(response => {
                if (response.ok) {
                    processResponse(response.clone());
                }
                return response;
            });
        }
        return originalFetch.apply(this, arguments);
    };

    // 2. 拦截 XMLHttpRequest
    const originalXHR = window.XMLHttpRequest;
    window.XMLHttpRequest = function() {
        const xhr = new originalXHR();
        const originalOpen = xhr.open;
        xhr.open = function(method, url) {
            if (isTargetApi(url)) {
                console.log('[拦截] XHR 请求:', url);
                const originalOnload = xhr.onload;
                xhr.onload = function() {
                    if (xhr.readyState === 4 && xhr.status === 200) {
                        processResponse(xhr.responseText);
                    }
                    originalOnload?.apply(this, arguments);
                };
            }
            return originalOpen.apply(this, arguments);
        };
        return xhr;
    };

    function isTargetApi(url) {
        if (typeof url !== 'string') return false;

        // 检查是否是token_holders API且包含limit参数
        const isTokenHoldersApi = /vas\/api\/v1\/token_holders\/(sol|eth|base|bsc|tron)(\/|$|\?)/i.test(url);
        const hasLimitParam = /[?&]limit=/i.test(url);

        const isTarget = isTokenHoldersApi && hasLimitParam;

        if (isTarget) {
            // 从URL中提取CA地址
            const match = url.match(/vas\/api\/v1\/token_holders\/sol\/([^/?]+)/i);
            console.log('匹配的ca:',match)
            console.log('包含limit参数的URL:', url)
            if (match && match[1]) {
                currentCaAddress = match[1];
            }
        }
        return isTarget;
    }

    function processResponse(response) {
        console.log('开始处理响应数据');

        try {
            const dataPromise = typeof response === 'string' ?
                  Promise.resolve(JSON.parse(response)) :
            response.json();

            dataPromise.then(data => {
                interceptedData = data;
                console.log('[成功] 拦截到数据量:', data.data?.list?.length);
                console.log('[成功] 拦截到数据:',data);

                const currentStats = calculateStats();
                if (isFirstLoad) {
                    // 首次加载,记录初始数据和CA地址
                    initialStats = currentStats;
                    initialCaAddress = currentCaAddress;
                    isFirstLoad = false;
                    updateStatsDisplay(currentStats, true);
                } else {
                    // 非首次加载,比较CA地址
                    const isSameCa = currentCaAddress === initialCaAddress;
                    updateStatsDisplay(currentStats, !isSameCa);

                    // 如果CA地址不同,更新初始数据为当前数据,并重置下载按钮状态
                    if (!isSameCa) {
                        initialStats = currentStats;
                        initialCaAddress = currentCaAddress;

                        // 重置下载按钮状态
                        resetDownloadButtonState();
                        console.log('检测到CA地址变更,已重置下载按钮状态');
                    }
                }
            }).catch(e => console.error('解析失败:', e));
        } catch (e) {
            console.error('处理响应错误:', e);
        }
    }


    // 3. 计算所有统计指标
    function calculateStats() {
        if (!interceptedData?.data?.list) return null;

        const currentTime = Math.floor(Date.now() / 1000);
        const sevenDaysInSeconds = 7 * 24 * 60 * 60; // 7天的秒数
        const holders = interceptedData.data.list;
        const stats = {
            fullPosition: 0,    // 全仓
            profitable: 0,      // 盈利
            losing: 0,         // 亏损
            active24h: 0,      // 24h活跃
            diamondHands: 0,   // 钻石手
            newAddress: 0,     // 新地址
            highProfit: 0,     // 10x盈利
            suspicious: 0,     // 新增:可疑地址
            holdingLessThan7Days: 0, // 新增:持仓小于7天
            lowSolBalance: 0,   // 新增:SOL餘額小於1的地址
            tokenTransferIn: 0, // 新增:代币转入地址数
            exchangeAddresses: 0 // 新增:交易所地址数
        };

        holders.forEach(holder => {
                // 满判断条件:1.没有卖出;2.没有出货地址
            if (holder.sell_amount_percentage === 0 &&
                (!holder.token_transfer_out || !holder.token_transfer_out.address)) {
                stats.fullPosition++;
            }
            if (holder.profit > 0) stats.profitable++;
            if (holder.profit < 0) stats.losing++;
            if (holder.last_active_timestamp > currentTime - 86400) stats.active24h++;
            if (holder.maker_token_tags?.includes('diamond_hands')) stats.diamondHands++;
            if (holder.tags?.includes('fresh_wallet')) stats.newAddress++;
            if (holder.profit_change > 5) stats.highProfit++;
            // 增强版可疑地址检测
            if (
                holder.is_suspicious ||
                holder.transfer_in ||
                (holder.maker_token_tags && (
                    holder.maker_token_tags.includes('rat_trader') ||
                    holder.maker_token_tags.includes('bundler')
                ))
            ) {
                stats.suspicious++;
            }
            // 新增7天持仓统计
            if (holder.start_holding_at &&
                (currentTime - holder.start_holding_at) < sevenDaysInSeconds) {
                stats.holdingLessThan7Days++;
            }
            // 新增低SOL餘額統計(小於1 SOL)
            if (holder.native_balance && (holder.native_balance / 1000000000) < 1) {
                stats.lowSolBalance++;
            }
            // 新增代币转入地址统计
            if (holder.token_transfer_in && holder.token_transfer_in.address && holder.token_transfer_in.address.trim() !== '') {
                stats.tokenTransferIn++;
            }
            // 新增交易所地址统计
            if (isExchangeAddress(holder)) {
                stats.exchangeAddresses++;
            }
        });
        return stats;
    }

    // 1. 持久化容器监听
    const observer = new MutationObserver(() => {
        const targetContainer = document.querySelector('.flex.overflow-x-auto.overflow-y-hidden.scroll-smooth.w-full');
        if (targetContainer && !targetContainer.querySelector('#statistic-gmgn-stats-item')) {
            injectStatsItem(targetContainer);
        }
    });

    function injectStatsItem(container) {
        if (container.querySelector('#statistic-gmgn-stats-item')) return;

        const isSol = isSolNetwork();
        const statsItem = document.createElement('div');
        statsItem.id = 'statistic-gmgn-stats-item';
        statsItem.className = 'statistic-gmgn-stats-container';

        const headerClass = isSol ? 'statistic-gmgn-stats-header sol-network' : 'statistic-gmgn-stats-header';
        const dataClass = isSol ? 'statistic-gmgn-stats-data sol-network' : 'statistic-gmgn-stats-data';

        statsItem.innerHTML = `
        <div class="${headerClass}">
    <span title="持有代币且未卖出任何数量的地址(排除转移代币卖出的地址)">满仓</span>
    <span title="当前持仓价值高于买入成本的地址">盈利</span>
    <span title="当前持仓价值低于买入成本的地址">亏损</span>
    <span title="过去24小时内有交易活动的地址">活跃</span>
    <span title="长期持有且很少卖出的地址">钻石</span>
    <span title="新钱包">新址</span>
    <span title="持仓时间小于7天的地址">7天</span>
    <span title="盈利超过5倍的地址">5X</span>
    <span title="标记为可疑或异常行为的地址">可疑</span>
    <span title="有代币转入记录的地址">转入</span>
    <span title="与交易所相关的地址">交易所</span>
    ${isSol ? '<span title="SOL餘額小於1的地址">低SOL</span>' : ''}
    <span title="下载统计数据图片">图片</span>
        </div>
        <div class="${dataClass}">
            <span id="fullPosition">-</span>
            <span id="profitable">-</span>
            <span id="losing">-</span>
            <span id="active24h">-</span>
            <span id="diamondHands">-</span>
            <span id="newAddress">-</span>
            <span id="holdingLessThan7Days">-</span>
            <span id="highProfit">-</span>
            <span id="suspicious">-</span>
            <span id="tokenTransferIn">-</span>
            <span id="exchangeAddresses">-</span>
            ${isSol ? '<span id="lowSolBalance">-</span>' : ''}
            <span id="statistic-download-image-btn" class="statistic-download-btn clickable" title="下载统计数据图片">下载</span>
        </div>
    `;
        container.insertAdjacentElement('afterbegin', statsItem);
    }

    function updateStatsDisplay(currentStats, forceNoArrows) {
        if (!currentStats) return;

        // 确保DOM已存在
        if (!document.getElementById('statistic-gmgn-stats-item')) {
            injectStatsItem();
        }

        const updateStatElement = (id, value, hasChanged, isIncrease) => {
            const element = document.getElementById(id);
            if (!element) return;

            element.innerHTML = `<strong style="color: ${id === 'profitable' ? '#2E8B57' :
            (id === 'losing' || id === 'suspicious' ? '#FF1493' :
             id === 'holdingLessThan7Days' ? '#00E5EE' :
             id === 'lowSolBalance' ? '#FFA500' : '#e9ecef')}">${value}</strong>`;

            // 只有当不是强制不显示箭头且确实有变化时才显示箭头
            if (!forceNoArrows && hasChanged) {
                const arrow = document.createElement('span');
                arrow.className = isIncrease ? 'statistic-up-arrow' : 'statistic-down-arrow';
                arrow.textContent = isIncrease ? '▲' : '▼';

                // 移除旧的箭头(如果有)
                const oldArrow = element.querySelector('.statistic-up-arrow, .statistic-down-arrow');
                if (oldArrow) oldArrow.remove();

                element.appendChild(arrow);
            } else {
                // 没有变化或强制不显示箭头,移除箭头(如果有)
                const oldArrow = element.querySelector('.statistic-up-arrow, .statistic-down-arrow');
                if (oldArrow) oldArrow.remove();
            }

            // 为所有统计类型添加点击事件监听器
            const baseClickableTypes = ['fullPosition', 'profitable', 'losing', 'active24h', 'diamondHands', 'newAddress', 'holdingLessThan7Days', 'highProfit', 'suspicious', 'tokenTransferIn', 'exchangeAddresses'];
            const clickableTypes = isSolNetwork() ? [...baseClickableTypes, 'lowSolBalance'] : baseClickableTypes;

            if (clickableTypes.includes(id)) {
                element.classList.add('clickable');
                element.onclick = (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    const addresses = getAddressByType(id);

                    // 交易所地址使用专用弹框
                    if (id === 'exchangeAddresses') {
                        createExchangeModal(addresses, currentCaAddress);
                    } else {
                        const title = getTypeTitle(id);
                        const showSolBalance = id === 'lowSolBalance';
                        createModal(title, addresses, currentCaAddress, showSolBalance);
                    }
                };
            } else {
                // 其他类型移除点击样式和事件
                element.classList.remove('clickable');
                element.onclick = null;
            }
        };

        // 绑定下载图片按钮事件
        const downloadBtn = document.getElementById('statistic-download-image-btn');
        if (downloadBtn && !downloadBtn.hasAttribute('data-event-bound')) {
            downloadBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();

                // 检查是否正在处理中
                if (isDownloadInProgress) {
                    console.log('下载正在进行中,请稍候...');
                    return;
                }

                handleDownloadImage();
            });
            downloadBtn.setAttribute('data-event-bound', 'true');
        }
        // 更新各个统计指标
            // 新增7天持仓统计更新
        updateStatElement('holdingLessThan7Days', currentStats.holdingLessThan7Days,
                          initialStats && currentStats.holdingLessThan7Days !== initialStats.holdingLessThan7Days,
                          initialStats && currentStats.holdingLessThan7Days > initialStats.holdingLessThan7Days);

        updateStatElement('fullPosition', currentStats.fullPosition,
                          initialStats && currentStats.fullPosition !== initialStats.fullPosition,
                          initialStats && currentStats.fullPosition > initialStats.fullPosition);

        updateStatElement('profitable', currentStats.profitable,
                          initialStats && currentStats.profitable !== initialStats.profitable,
                          initialStats && currentStats.profitable > initialStats.profitable);
        updateStatElement('losing', currentStats.losing,
                          currentStats.losing !== initialStats.losing,
                          currentStats.losing > initialStats.losing);

        updateStatElement('active24h', currentStats.active24h,
                          currentStats.active24h !== initialStats.active24h,
                          currentStats.active24h > initialStats.active24h);

        updateStatElement('diamondHands', currentStats.diamondHands,
                          currentStats.diamondHands !== initialStats.diamondHands,
                          currentStats.diamondHands > initialStats.diamondHands);

        updateStatElement('newAddress', currentStats.newAddress,
                          currentStats.newAddress !== initialStats.newAddress,
                          currentStats.newAddress > initialStats.newAddress);

        updateStatElement('highProfit', currentStats.highProfit,
                          currentStats.highProfit !== initialStats.highProfit,
                          currentStats.highProfit > initialStats.highProfit);

        updateStatElement('suspicious', currentStats.suspicious,
                          currentStats.suspicious !== initialStats.suspicious,
                          currentStats.suspicious > initialStats.suspicious);

        updateStatElement('tokenTransferIn', currentStats.tokenTransferIn,
                          initialStats && currentStats.tokenTransferIn !== initialStats.tokenTransferIn,
                          initialStats && currentStats.tokenTransferIn > initialStats.tokenTransferIn);

        updateStatElement('exchangeAddresses', currentStats.exchangeAddresses,
                          initialStats && currentStats.exchangeAddresses !== initialStats.exchangeAddresses,
                          initialStats && currentStats.exchangeAddresses > initialStats.exchangeAddresses);

        // 只在SOL网络时更新低SOL余额统计
        if (isSolNetwork()) {
            updateStatElement('lowSolBalance', currentStats.lowSolBalance,
                              initialStats && currentStats.lowSolBalance !== initialStats.lowSolBalance,
                              initialStats && currentStats.lowSolBalance > initialStats.lowSolBalance);
        }
    }

    // 数据收集函数 - 收集基础统计数据和详细持有者信息
    function collectStatsData() {
        if (!interceptedData?.data?.list || !currentCaAddress) {
            console.error('数据不完整,无法生成图片');
            return null;
        }

        const currentStats = calculateStats();
        if (!currentStats) {
            console.error('无法计算统计数据');
            return null;
        }

        // 基础统计数据
        const basicStats = {
            fullPosition: { label: '满仓', value: currentStats.fullPosition, type: 'fullPosition' },
            profitable: { label: '盈利', value: currentStats.profitable, type: 'profitable' },
            losing: { label: '亏损', value: currentStats.losing, type: 'losing' },
            active24h: { label: '活跃', value: currentStats.active24h, type: 'active24h' },
            diamondHands: { label: '钻石', value: currentStats.diamondHands, type: 'diamondHands' },
            newAddress: { label: '新址', value: currentStats.newAddress, type: 'newAddress' },
            holdingLessThan7Days: { label: '7天', value: currentStats.holdingLessThan7Days, type: 'holdingLessThan7Days' },
            highProfit: { label: '5X', value: currentStats.highProfit, type: 'highProfit' },
            suspicious: { label: '可疑', value: currentStats.suspicious, type: 'suspicious' },
            tokenTransferIn: { label: '转入', value: currentStats.tokenTransferIn, type: 'tokenTransferIn' },
            exchangeAddresses: { label: '交易所', value: currentStats.exchangeAddresses, type: 'exchangeAddresses' }
        };

        // 如果是SOL网络,添加低余额统计
        if (isSolNetwork()) {
            basicStats.lowSolBalance = { label: '低SOL', value: currentStats.lowSolBalance, type: 'lowSolBalance' };
        }

        // 收集每个统计类型的汇总数据(包括值为0的项目)
        const detailedData = {};
        for (const [key, stat] of Object.entries(basicStats)) {
            const addresses = getAddressByType(stat.type);
            if (addresses && addresses.length > 0) {
                // 计算汇总信息
                const soldChipsCount = addresses.filter(holder => (holder.sell_amount_percentage || 0) > 0).length;
                const totalHoldingPercentage = addresses.reduce((sum, holder) => sum + (holder.amount_percentage || 0), 0);

                detailedData[key] = {
                    label: stat.label,
                    totalCount: addresses.length,
                    soldChipsCount: soldChipsCount,
                    totalHoldingPercentage: (totalHoldingPercentage * 100).toFixed(2) + '%'
                };
            } else {
                // 即使没有地址数据,也创建空的详细数据
                detailedData[key] = {
                    label: stat.label,
                    totalCount: 0,
                    soldChipsCount: 0,
                    totalHoldingPercentage: '0.00%'
                };
            }
        }

        return {
            caAddress: currentCaAddress,
            timestamp: new Date(),
            basicStats: basicStats,
            detailedData: detailedData
        };
    }

    // 图片生成函数
    function generateStatsImage(data) {
        if (!data) {
            console.error('无数据可生成图片');
            return null;
        }

        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');

        // 设置画布尺寸
        canvas.width = 1180;
        canvas.height = 1200; // 调整高度以适应所有数据

        // 设置背景
        ctx.fillStyle = '#1e293b';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // 添加边框
        ctx.strokeStyle = '#0077ff';
        ctx.lineWidth = 2;
        ctx.strokeRect(10, 10, canvas.width - 20, canvas.height - 20);

        // 设置字体
        ctx.font = 'bold 24px Arial';
        ctx.fillStyle = '#ffffff';
        ctx.textAlign = 'center';

        // 绘制标题
        const title = 'GMGN 前排统计分析';
        ctx.fillText(title, canvas.width / 2, 50);

        // 绘制CA地址和时间
        ctx.font = '16px Arial';
        ctx.fillStyle = '#00ff88';
        const formatTime = data.timestamp.getFullYear() +
            '-' + String(data.timestamp.getMonth() + 1).padStart(2, '0') +
            '-' + String(data.timestamp.getDate()).padStart(2, '0') +
            ' ' + String(data.timestamp.getHours()).padStart(2, '0') +
            ':' + String(data.timestamp.getMinutes()).padStart(2, '0') +
            ':' + String(data.timestamp.getSeconds()).padStart(2, '0');
        ctx.fillText(`CA: ${data.caAddress}`, canvas.width / 2, 80);
        ctx.fillText(`时间: ${formatTime}`, canvas.width / 2, 100);

        // 绘制基础统计数据(第一层)
        ctx.font = 'bold 20px Arial';
        ctx.fillStyle = '#ffffff';
        ctx.textAlign = 'left';
        ctx.fillText('基础统计数据:', 120, 150);

        let yPos = 180;
        const statsPerRow = 3; // 改为每行3个,与详细数据分析一致
        const statWidth = 320; // 调整为320px,与详细数据分析完全一致
        const statHeight = 60;
        let currentRow = 0;
        let currentCol = 0;

        for (const [key, stat] of Object.entries(data.basicStats)) {
            const x = 120 + currentCol * statWidth; // 居中对齐:(1200-960)/2 = 120px
            const y = yPos + currentRow * statHeight;

            // 绘制统计项背景
            ctx.fillStyle = 'rgba(0, 119, 255, 0.1)';
            ctx.fillRect(x, y, statWidth - 20, statHeight - 10);

            // 绘制统计项边框
            ctx.strokeStyle = '#0077ff';
            ctx.lineWidth = 1;
            ctx.strokeRect(x, y, statWidth - 20, statHeight - 10);

            // 绘制标签
            ctx.font = '16px Arial';
            ctx.fillStyle = '#cccccc';
            ctx.fillText(stat.label, x + 10, y + 25);

            // 绘制数值
            ctx.font = 'bold 20px Arial';
            const valueColor = key === 'profitable' ? '#2E8B57' :
                              (key === 'losing' || key === 'suspicious' ? '#FF1493' :
                               key === 'holdingLessThan7Days' ? '#00E5EE' :
                               key === 'lowSolBalance' ? '#FFA500' : '#00ff00');
            ctx.fillStyle = valueColor;
            ctx.fillText(stat.value.toString(), x + 10, y + 45);

            currentCol++;
            if (currentCol >= statsPerRow) {
                currentCol = 0;
                currentRow++;
            }
        }

        // 绘制详细数据(第二层)
        yPos = 180 + (Math.ceil(Object.keys(data.basicStats).length / statsPerRow) + 1) * statHeight + 50;

        // 重置文本对齐方式为左对齐
        ctx.textAlign = 'left';
        ctx.font = 'bold 20px Arial';
        ctx.fillStyle = '#ffffff';
        ctx.fillText('详细数据分析:', 120, yPos);

        yPos += 40;

        // 使用网格布局绘制详细数据分析
        const detailStatsPerRow = 3; // 每行3个详细数据单元格
        const detailStatWidth = 320; // 减小宽度确保不超出边框
        const detailStatHeight = 120;
        let detailCurrentRow = 0;
        let detailCurrentCol = 0;

        for (const [key, detail] of Object.entries(data.detailedData)) {
            if (yPos + detailCurrentRow * detailStatHeight > canvas.height - 150) break; // 防止超出画布

            const x = 120 + detailCurrentCol * detailStatWidth; // 与基础数据对齐
            const y = yPos + detailCurrentRow * detailStatHeight;

            // 绘制详细统计项背景(与基础统计数据相同)
            ctx.fillStyle = 'rgba(0, 119, 255, 0.1)';
            ctx.fillRect(x, y, detailStatWidth - 20, detailStatHeight - 10);

            // 绘制详细统计项边框(与基础统计数据相同)
            ctx.strokeStyle = '#0077ff';
            ctx.lineWidth = 1;
            ctx.strokeRect(x, y, detailStatWidth - 20, detailStatHeight - 10);

            // 绘制分类标题(与基础统计数据标签样式相同)
            ctx.font = '16px Arial';
            ctx.fillStyle = '#00ff88';
            ctx.textAlign = 'left';
            ctx.fillText(`${detail.label}`, x + 15, y + 25);

            // 绘制汇总数据
            ctx.font = '15px Arial';
            ctx.fillStyle = '#cccccc';

            // 已卖筹码数
            ctx.fillText('已卖筹码数:', x + 15, y + 50);
            ctx.font = 'bold 16px Arial';
            ctx.fillStyle = detail.soldChipsCount > 0 ? '#ff4444' : '#00ff88';
            ctx.fillText(detail.soldChipsCount.toString(), x + 120, y + 50);

            // 总地址数
            ctx.font = '15px Arial';
            ctx.fillStyle = '#cccccc';
            ctx.fillText('总地址数:', x + 15, y + 75);
            ctx.font = 'bold 16px Arial';
            // 根据分类类型设置颜色
            const categoryColor = key === 'profitable' ? '#2E8B57' :
                                (key === 'losing' || key === 'suspicious' ? '#FF1493' :
                                 key === 'holdingLessThan7Days' ? '#00E5EE' :
                                 key === 'lowSolBalance' ? '#FFA500' : '#00ff88');
            ctx.fillStyle = categoryColor;
            ctx.fillText(detail.totalCount.toString(), x + 120, y + 75);

            // 持仓占比
            ctx.font = '15px Arial';
            ctx.fillStyle = '#cccccc';
            ctx.fillText('持仓占比:', x + 15, y + 100);
            ctx.font = 'bold 16px Arial';
            ctx.fillStyle = '#60a5fa';
            ctx.fillText(detail.totalHoldingPercentage, x + 120, y + 100);

            detailCurrentCol++;
            if (detailCurrentCol >= detailStatsPerRow) {
                detailCurrentCol = 0;
                detailCurrentRow++;
            }
        }

        return canvas;
    }

    // 下载图片函数
    function downloadImage(canvas, filename) {
        if (!canvas) {
            console.error('无法下载图片:画布为空');
            return;
        }

        try {
            // 转换为blob
            canvas.toBlob(function(blob) {
                // 创建下载链接
                const url = URL.createObjectURL(blob);
                const link = document.createElement('a');
                link.href = url;
                link.download = filename;

                // 触发下载
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);

                // 清理URL对象
                URL.revokeObjectURL(url);

                console.log('图片下载成功:', filename);
            }, 'image/png');
        } catch (error) {
            console.error('下载图片失败:', error);
        }
    }

    // 显示图片预览模态框
    function showImagePreview(canvas, filename) {
        const modal = document.createElement('div');
        modal.className = 'image-preview-modal';

        const imageUrl = canvas.toDataURL('image/png');

        modal.innerHTML = `
            <div class="image-preview-content">
                <div class="image-preview-header">
                    <div class="image-preview-title">📷 统计图片预览</div>
                    <button class="image-preview-close">&times;</button>
                </div>
                <img src="${imageUrl}" alt="统计图片" class="image-preview-img">
                <div class="image-preview-buttons">
                    <button class="image-preview-btn copy-btn">📋 复制图片</button>
                    <button class="image-preview-btn download-btn">💾 下载图片</button>
                </div>
            </div>
        `;

        document.body.appendChild(modal);

        // 绑定事件
        const closeBtn = modal.querySelector('.image-preview-close');
        const copyBtn = modal.querySelector('.copy-btn');
        const downloadBtn = modal.querySelector('.download-btn');

        // 关闭模态框
        const closeModal = () => {
            document.body.removeChild(modal);
        };

        closeBtn.addEventListener('click', closeModal);
        modal.addEventListener('click', (e) => {
            if (e.target === modal) closeModal();
        });

        // 复制图片
        copyBtn.addEventListener('click', () => {
            copyImageToClipboard(canvas);
        });

        // 下载图片
        downloadBtn.addEventListener('click', () => {
            downloadImageFromPreview(canvas, filename);
            closeModal();
        });

        // ESC键关闭
        const escHandler = (e) => {
            if (e.key === 'Escape') {
                closeModal();
                document.removeEventListener('keydown', escHandler);
            }
        };
        document.addEventListener('keydown', escHandler);
    }

    // 复制图片到剪贴板
    async function copyImageToClipboard(canvas) {
        try {
            // 将canvas转为blob
            canvas.toBlob(async (blob) => {
                try {
                    if (navigator.clipboard && window.ClipboardItem) {
                        const item = new ClipboardItem({ 'image/png': blob });
                        await navigator.clipboard.write([item]);
                        showModernToast('图片已复制到剪贴板!', 'success');
                    } else {
                        // 兜底方案:创建临时图片元素让用户手动复制
                        const img = document.createElement('img');
                        img.src = canvas.toDataURL('image/png');
                        img.style.position = 'fixed';
                        img.style.top = '-9999px';
                        document.body.appendChild(img);

                        // 选择图片
                        const range = document.createRange();
                        range.selectNode(img);
                        window.getSelection().removeAllRanges();
                        window.getSelection().addRange(range);

                        // 尝试复制
                        const success = document.execCommand('copy');
                        document.body.removeChild(img);
                        window.getSelection().removeAllRanges();

                        if (success) {
                            showModernToast('图片已复制到剪贴板!', 'success');
                        } else {
                            showModernToast('复制失败,请尝试手动下载图片', 'error');
                        }
                    }
                } catch (error) {
                    console.error('复制图片失败:', error);
                    showModernToast('复制失败:' + error.message, 'error');
                }
            }, 'image/png');
        } catch (error) {
            console.error('复制图片失败:', error);
            showModernToast('复制失败:' + error.message, 'error');
        }
    }

    // 从预览下载图片
    function downloadImageFromPreview(canvas, filename) {
        try {
            canvas.toBlob((blob) => {
                const url = URL.createObjectURL(blob);
                const link = document.createElement('a');
                link.href = url;
                link.download = filename;

                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);

                URL.revokeObjectURL(url);
                showModernToast('图片下载成功!', 'success');
            }, 'image/png');
        } catch (error) {
            console.error('下载图片失败:', error);
            showModernToast('下载失败:' + error.message, 'error');
        }
    }

    // 重置按钮状态
    function resetDownloadButtonState() {
        isDownloadInProgress = false;
        const button = document.getElementById('statistic-download-image-btn');
        if (button) {
            button.classList.remove('disabled');
            button.textContent = '下载';
        }
    }

    // 设置按钮禁用状态
    function setDownloadButtonDisabled(disabled) {
        const button = document.getElementById('statistic-download-image-btn');
        if (button) {
            if (disabled) {
                button.classList.add('disabled');
                button.textContent = '生成中...';
            } else {
                button.classList.remove('disabled');
                button.textContent = '下载';
            }
        }
    }

    // 主要的下载处理函数 - 现在显示预览而不是直接下载
    function handleDownloadImage() {
        const button = document.getElementById('statistic-download-image-btn');
        if (!button) return;

        // 检查是否已在处理中
        if (isDownloadInProgress) {
            console.log('图片生成正在进行中...');
            return;
        }

        // 设置处理状态
        isDownloadInProgress = true;
        setDownloadButtonDisabled(true);

        try {
            // 收集数据
            const data = collectStatsData();
            if (!data) {
                throw new Error('无法收集数据');
            }

            // 更新当前CA地址
            currentCAAddress = data.caAddress || '';

            // 生成图片
            const canvas = generateStatsImage(data);
            if (!canvas) {
                throw new Error('无法生成图片');
            }

            // 生成文件名
            const timestamp = data.timestamp.getFullYear() +
                String(data.timestamp.getMonth() + 1).padStart(2, '0') +
                String(data.timestamp.getDate()).padStart(2, '0') +
                String(data.timestamp.getHours()).padStart(2, '0');
            const filename = `${data.caAddress}_${timestamp}.png`;

            // 显示预览而不是直接下载
            showImagePreview(canvas, filename);

        } catch (error) {
            console.error('生成图片失败:', error);
            showModernToast('生成图片失败:' + error.message, 'error');
        } finally {
            // 恢复按钮状态
            isDownloadInProgress = false;
            setDownloadButtonDisabled(false);
        }
    }

    // 4. 初始化
    if (document.readyState === 'complete') {
        startObserving();
    } else {
        window.addEventListener('DOMContentLoaded', startObserving);
    }

    function startObserving() {
        // 立即检查一次
        const initialContainer = document.querySelector('.flex.overflow-x-auto.overflow-y-hidden.scroll-smooth.w-full');
        if (initialContainer) injectStatsItem(initialContainer);

        // 持续监听DOM变化
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: false
        });
    }
})();