Greasy Fork

Ultimate Web Optimizer

全面的网页性能优化方案(可视化配置版)- 懒加载/预加载/预连接/布局优化

当前为 2025-06-10 提交的版本,查看 最新版本

// ==UserScript==
// @name         Ultimate Web Optimizer
// @namespace    https://greasyfork.org/zh-CN/users/1474228-moyu001
// @version      2.0
// @description  全面的网页性能优化方案(可视化配置版)- 懒加载/预加载/预连接/布局优化
// @author       moyu001
// @match        *://*/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_log
// @license      MIT
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // ========================
    // 工具函数 - 提前定义
    // ========================

    /**
     * 防抖函数
     * @param {Function} fn 要防抖的函数
     * @param {number} delay 延迟时间
     * @returns {Function} 防抖后的函数
     */
    function debounce(fn, delay) {
        let timer = null;
        return function(...args) {
            clearTimeout(timer);
            timer = setTimeout(() => fn.apply(this, args), delay);
        };
    }

    /**
     * 节流函数
     * @param {Function} func 要节流的函数
     * @param {number} limit 限制时间
     * @returns {Function} 节流后的函数
     */
    function throttle(func, limit) {
        let inThrottle;
        return function(...args) {
            if (!inThrottle) {
                func.apply(this, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }

    /**
     * 安全的 URL 解析
     * @param {string} url URL 字符串
     * @param {string} base 基准 URL
     * @returns {URL|null} URL 对象或 null
     */
    function safeParseURL(url, base) {
        try {
            return new URL(url, base);
        } catch {
            return null;
        }
    }

    /**
     * 检查元素是否可见
     * @param {Element} element 要检查的元素
     * @returns {boolean} 是否可见
     */
    function isElementVisible(element) {
        if (!element) return false;
        const style = window.getComputedStyle(element);
        return style.display !== 'none' &&
               style.visibility !== 'hidden' &&
               style.opacity !== '0';
    }

    /**
     * 深度合并对象
     * @param {Object} target 目标对象
     * @param {Object} source 源对象
     * @returns {Object} 合并后的对象
     */
    function deepMerge(target, source) {
        const result = { ...target };

        for (const key in source) {
            if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
                result[key] = deepMerge(result[key] || {}, source[key]);
            } else {
                result[key] = source[key];
            }
        }

        return result;
    }

    /**
     * 检查是否为 HTML 图片元素 - 增强类型检查
     * @param {Node} node DOM 节点
     * @returns {boolean} 是否为图片元素
     */
    function isImageElement(node) {
        return node instanceof HTMLImageElement;
    }

    /**
     * 延迟函数
     * @param {number} ms 延迟毫秒数
     * @returns {Promise} Promise 对象
     */
    function delay(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    /**
     * 简单的 LRU 缓存实现
     */
    class LRUCache {
        constructor(maxSize = 100) {
            this.maxSize = maxSize;
            this.cache = new Map();
        }

        get(key) {
            if (this.cache.has(key)) {
                const value = this.cache.get(key);
                this.cache.delete(key);
                this.cache.set(key, value);
                return value;
            }
            return null;
        }

        set(key, value) {
            if (this.cache.has(key)) {
                this.cache.delete(key);
            } else if (this.cache.size >= this.maxSize) {
                const firstKey = this.cache.keys().next().value;
                this.cache.delete(firstKey);
            }
            this.cache.set(key, value);
        }

        has(key) {
            return this.cache.has(key);
        }

        clear() {
            this.cache.clear();
        }

        get size() {
            return this.cache.size;
        }
    }

    /**
     * 重试操作工具类 - 新增错误重试机制
     */
    class RetryableOperation {
        /**
         * 执行带重试的操作
         * @param {Function} operation 要执行的操作
         * @param {number} maxRetries 最大重试次数
         * @param {number} baseDelay 基础延迟时间
         * @returns {Promise} 操作结果
         */
        static async executeWithRetry(operation, maxRetries = 3, baseDelay = 1000) {
            for (let i = 0; i < maxRetries; i++) {
                try {
                    return await operation();
                } catch (e) {
                    if (i === maxRetries - 1) throw e;
                    await delay(baseDelay * (i + 1));
                }
            }
        }
    }

    /**
     * 性能监控器
     */
    class PerformanceMonitor {
        constructor(debug = false) {
            this.debug = debug;
            this.metrics = new Map();
            this.counters = new Map();
        }

        start(name) {
            if (this.debug) {
                this.metrics.set(name, performance.now());
            }
        }

        end(name) {
            if (this.debug && this.metrics.has(name)) {
                const duration = performance.now() - this.metrics.get(name);
                console.log(`[性能] ${name}: ${duration.toFixed(2)}ms`);
                this.metrics.delete(name);
                return duration;
            }
            return 0;
        }

        count(name) {
            if (this.debug) {
                this.counters.set(name, (this.counters.get(name) || 0) + 1);
            }
        }

        getCounter(name) {
            return this.counters.get(name) || 0;
        }

        profile(name, fn) {
            if (!this.debug) return fn();

            const start = performance.now();
            const result = fn();
            const end = performance.now();
            console.log(`[性能] ${name}: ${(end - start).toFixed(2)}ms`);
            return result;
        }

        log(message, ...args) {
            if (this.debug) {
                console.log(`[优化器] ${message}`, ...args);
            }
        }

        warn(message, ...args) {
            if (this.debug) {
                console.warn(`[优化器] ${message}`, ...args);
            }
        }

        error(message, ...args) {
            if (this.debug) {
                console.error(`[优化器] ${message}`, ...args);
            }
        }
    }

    // ========================
    // 可视化配置界面
    // ========================

    /**
     * 可视化配置管理器
     */
    class VisualConfigManager {
        constructor(configManager) {
            this.configManager = configManager;
            this.isVisible = false;
            this.configPanel = null;
            this.dragOffset = { x: 0, y: 0 };
            this.isDragging = false;

            this.createConfigPanel();
            this.setupKeyboardShortcut();
        }

        createConfigPanel() {
            // 创建样式
            this.injectStyles();

            // 创建主面板
            this.configPanel = document.createElement('div');
            this.configPanel.id = 'web-optimizer-config';
            this.configPanel.className = 'wo-config-panel wo-hidden';

            this.configPanel.innerHTML = this.generatePanelHTML();
            document.body.appendChild(this.configPanel);

            // 绑定事件
            this.bindEvents();
        }

        injectStyles() {
            const style = document.createElement('style');
            style.id = 'web-optimizer-styles';
            style.textContent = `
                .wo-config-panel {
                    position: fixed;
                    top: 50px;
                    right: 20px;
                    width: 400px;
                    max-height: 80vh;
                    background: #ffffff;
                    border: 1px solid #e1e5e9;
                    border-radius: 12px;
                    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);
                    z-index: 2147483647;
                    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
                    font-size: 14px;
                    line-height: 1.5;
                    overflow: hidden;
                    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                    backdrop-filter: blur(10px);
                }

                .wo-config-panel.wo-hidden {
                    opacity: 0;
                    visibility: hidden;
                    transform: translateX(100%) scale(0.95);
                }

                .wo-config-header {
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    color: white;
                    padding: 16px 20px;
                    cursor: move;
                    user-select: none;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                }

                .wo-config-title {
                    font-weight: 600;
                    font-size: 16px;
                    margin: 0;
                }

                .wo-config-version {
                    background: rgba(255, 255, 255, 0.2);
                    padding: 2px 8px;
                    border-radius: 12px;
                    font-size: 11px;
                    font-weight: 500;
                }

                .wo-config-close {
                    background: none;
                    border: none;
                    color: white;
                    font-size: 20px;
                    cursor: pointer;
                    padding: 4px;
                    border-radius: 4px;
                    transition: background-color 0.2s;
                }

                .wo-config-close:hover {
                    background: rgba(255, 255, 255, 0.2);
                }

                .wo-config-content {
                    max-height: calc(80vh - 80px);
                    overflow-y: auto;
                    padding: 0;
                }

                .wo-config-content::-webkit-scrollbar {
                    width: 6px;
                }

                .wo-config-content::-webkit-scrollbar-thumb {
                    background: #c1c1c1;
                    border-radius: 3px;
                }

                .wo-config-section {
                    border-bottom: 1px solid #f0f0f0;
                }

                .wo-config-section:last-child {
                    border-bottom: none;
                }

                .wo-section-header {
                    background: #f8f9fa;
                    padding: 12px 20px;
                    font-weight: 600;
                    color: #2c3e50;
                    border-left: 4px solid #667eea;
                    cursor: pointer;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    transition: background-color 0.2s;
                }

                .wo-section-header:hover {
                    background: #e9ecef;
                }

                .wo-section-toggle {
                    font-size: 12px;
                    transition: transform 0.2s;
                }

                .wo-section-toggle.collapsed {
                    transform: rotate(-90deg);
                }

                .wo-section-content {
                    padding: 16px 20px;
                    display: block;
                }

                .wo-section-content.collapsed {
                    display: none;
                }

                .wo-config-item {
                    margin-bottom: 16px;
                }

                .wo-config-item:last-child {
                    margin-bottom: 0;
                }

                .wo-config-label {
                    display: block;
                    font-weight: 500;
                    color: #2c3e50;
                    margin-bottom: 6px;
                }

                .wo-config-description {
                    font-size: 12px;
                    color: #6c757d;
                    margin-bottom: 8px;
                    line-height: 1.4;
                }

                .wo-config-input {
                    width: 100%;
                    padding: 8px 12px;
                    border: 1px solid #ddd;
                    border-radius: 6px;
                    font-size: 14px;
                    transition: border-color 0.2s, box-shadow 0.2s;
                    box-sizing: border-box;
                }

                .wo-config-input:focus {
                    outline: none;
                    border-color: #667eea;
                    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
                }

                .wo-config-checkbox {
                    display: flex;
                    align-items: center;
                    cursor: pointer;
                }

                .wo-config-checkbox input {
                    margin-right: 8px;
                    transform: scale(1.2);
                }

                .wo-config-textarea {
                    width: 100%;
                    min-height: 80px;
                    padding: 8px 12px;
                    border: 1px solid #ddd;
                    border-radius: 6px;
                    font-size: 13px;
                    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
                    resize: vertical;
                    box-sizing: border-box;
                }

                .wo-config-actions {
                    padding: 16px 20px;
                    background: #f8f9fa;
                    border-top: 1px solid #e1e5e9;
                    display: flex;
                    gap: 8px;
                }

                .wo-btn {
                    padding: 8px 16px;
                    border: none;
                    border-radius: 6px;
                    font-size: 13px;
                    font-weight: 500;
                    cursor: pointer;
                    transition: all 0.2s;
                    flex: 1;
                }

                .wo-btn-primary {
                    background: #667eea;
                    color: white;
                }

                .wo-btn-primary:hover {
                    background: #5a67d8;
                    transform: translateY(-1px);
                }

                .wo-btn-secondary {
                    background: #e2e8f0;
                    color: #4a5568;
                }

                .wo-btn-secondary:hover {
                    background: #cbd5e0;
                }

                .wo-btn-danger {
                    background: #e53e3e;
                    color: white;
                }

                .wo-btn-danger:hover {
                    background: #c53030;
                }

                .wo-stats-grid {
                    display: grid;
                    grid-template-columns: 1fr 1fr;
                    gap: 12px;
                    margin-top: 12px;
                }

                .wo-stat-item {
                    background: #f8f9fa;
                    padding: 12px;
                    border-radius: 6px;
                    text-align: center;
                }

                .wo-stat-value {
                    font-size: 18px;
                    font-weight: 600;
                    color: #667eea;
                    display: block;
                }

                .wo-stat-label {
                    font-size: 11px;
                    color: #6c757d;
                    margin-top: 2px;
                }

                .wo-toggle-btn {
                    position: fixed;
                    bottom: 20px;
                    right: 20px;
                    width: 56px;
                    height: 56px;
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    border: none;
                    border-radius: 50%;
                    color: white;
                    font-size: 20px;
                    cursor: pointer;
                    box-shadow: 0 4px 16px rgba(102, 126, 234, 0.4);
                    z-index: 2147483646;
                    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }

                .wo-toggle-btn:hover {
                    transform: translateY(-2px);
                    box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
                }

                .wo-toggle-btn.wo-hidden {
                    opacity: 0;
                    visibility: hidden;
                    transform: translateY(100px) scale(0.8);
                }

                @media (max-width: 480px) {
                    .wo-config-panel {
                        width: calc(100vw - 40px);
                        right: 20px;
                        left: 20px;
                        max-height: 90vh;
                    }
                }
            `;
            document.head.appendChild(style);
        }

        generatePanelHTML() {
            const config = this.configManager.config;

            return `
                <div class="wo-config-header">
                    <div>
                        <h3 class="wo-config-title">Web Optimizer 配置</h3>
                    </div>
                    <div style="display: flex; align-items: center; gap: 12px;">
                        <span class="wo-config-version">v2.0</span>
                        <button class="wo-config-close">×</button>
                    </div>
                </div>

                <div class="wo-config-content">
                    ${this.generateGeneralSection(config)}
                    ${this.generateLazyLoadSection(config)}
                    ${this.generatePreconnectSection(config)}
                    ${this.generatePreloadSection(config)}
                    ${this.generateLayoutSection(config)}
                    ${this.generateStatsSection()}
                </div>

                <div class="wo-config-actions">
                    <button class="wo-btn wo-btn-primary" data-action="save">保存配置</button>
                    <button class="wo-btn wo-btn-secondary" data-action="reset">重置默认</button>
                    <button class="wo-btn wo-btn-danger" data-action="export">导出配置</button>
                </div>
            `;
        }

        generateGeneralSection(config) {
            return `
                <div class="wo-config-section">
                    <div class="wo-section-header" data-section="general">
                        <span>🔧 基础设置</span>
                        <span class="wo-section-toggle">▼</span>
                    </div>
                    <div class="wo-section-content" data-content="general">
                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="debug" ${config.debug ? 'checked' : ''}>
                                启用调试模式
                            </label>
                            <div class="wo-config-description">
                                开启后将在控制台显示详细的运行日志和性能信息
                            </div>
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">全局黑名单</label>
                            <div class="wo-config-description">
                                这些域名将完全跳过所有优化功能,每行一个域名
                            </div>
                            <textarea class="wo-config-textarea" data-path="globalBlacklist" placeholder="example.com">${config.globalBlacklist.join('\n')}</textarea>
                        </div>
                    </div>
                </div>
            `;
        }

        generateLazyLoadSection(config) {
            const lazyLoad = config.lazyLoad;
            return `
                <div class="wo-config-section">
                    <div class="wo-section-header" data-section="lazyload">
                        <span>🖼️ 懒加载设置</span>
                        <span class="wo-section-toggle">▼</span>
                    </div>
                    <div class="wo-section-content" data-content="lazyload">
                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="lazyLoad.enabled" ${lazyLoad.enabled ? 'checked' : ''}>
                                启用图片懒加载
                            </label>
                            <div class="wo-config-description">
                                自动延迟加载页面图片,提升页面加载速度
                            </div>
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">最小处理尺寸 (像素)</label>
                            <div class="wo-config-description">
                                小于此尺寸的图片将不进行懒加载处理
                            </div>
                            <input type="number" class="wo-config-input" data-path="lazyLoad.minSize" value="${lazyLoad.minSize}" min="0" max="500">
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">预加载边距</label>
                            <div class="wo-config-description">
                                图片距离视窗多远时开始加载(如:200px)
                            </div>
                            <input type="text" class="wo-config-input" data-path="lazyLoad.rootMargin" value="${lazyLoad.rootMargin}" placeholder="200px">
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">批处理大小</label>
                            <div class="wo-config-description">
                                每次处理的图片数量,较大值处理更快但可能影响性能
                            </div>
                            <input type="number" class="wo-config-input" data-path="lazyLoad.batchSize" value="${lazyLoad.batchSize}" min="8" max="128">
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="lazyLoad.skipHidden" ${lazyLoad.skipHidden ? 'checked' : ''}>
                                跳过隐藏图片
                            </label>
                            <div class="wo-config-description">
                                不处理当前不可见的图片元素
                            </div>
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">黑名单</label>
                            <div class="wo-config-description">
                                这些域名将跳过懒加载功能,每行一个域名
                            </div>
                            <textarea class="wo-config-textarea" data-path="lazyLoad.blacklist" placeholder="images.example.com">${lazyLoad.blacklist.join('\n')}</textarea>
                        </div>
                    </div>
                </div>
            `;
        }

        generatePreconnectSection(config) {
            const preconnect = config.preconnect;
            return `
                <div class="wo-config-section">
                    <div class="wo-section-header" data-section="preconnect">
                        <span>🔗 预连接设置</span>
                        <span class="wo-section-toggle">▼</span>
                    </div>
                    <div class="wo-section-content" data-content="preconnect">
                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="preconnect.enabled" ${preconnect.enabled ? 'checked' : ''}>
                                启用智能预连接
                            </label>
                            <div class="wo-config-description">
                                自动预连接到常用CDN和资源服务器,减少连接延迟
                            </div>
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">最大连接数</label>
                            <div class="wo-config-description">
                                同时预连接的最大域名数量
                            </div>
                            <input type="number" class="wo-config-input" data-path="preconnect.maxConnections" value="${preconnect.maxConnections}" min="1" max="20">
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">预连接白名单</label>
                            <div class="wo-config-description">
                                符合这些域名的资源将被预连接,每行一个域名
                            </div>
                            <textarea class="wo-config-textarea" data-path="preconnect.whitelist" style="min-height: 120px;">${preconnect.whitelist.join('\n')}</textarea>
                        </div>
                    </div>
                </div>
            `;
        }

        generatePreloadSection(config) {
            const preload = config.preload;
            return `
                <div class="wo-config-section">
                    <div class="wo-section-header" data-section="preload">
                        <span>📦 预加载设置</span>
                        <span class="wo-section-toggle">▼</span>
                    </div>
                    <div class="wo-section-content" data-content="preload">
                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="preload.enabled" ${preload.enabled ? 'checked' : ''}>
                                启用资源预加载
                            </label>
                            <div class="wo-config-description">
                                预加载关键CSS、JS和字体资源,提升加载速度
                            </div>
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">最大预加载数</label>
                            <div class="wo-config-description">
                                同时预加载的最大资源数量
                            </div>
                            <input type="number" class="wo-config-input" data-path="preload.maxPreloads" value="${preload.maxPreloads}" min="1" max="20">
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">支持的文件类型</label>
                            <div class="wo-config-description">
                                将预加载这些类型的文件,用逗号分隔
                            </div>
                            <input type="text" class="wo-config-input" data-path="preload.types" value="${preload.types.join(', ')}" placeholder="css, js, woff2, woff">
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">请求超时时间 (毫秒)</label>
                            <div class="wo-config-description">
                                获取CSS文件以提取字体的超时时间
                            </div>
                            <input type="number" class="wo-config-input" data-path="preload.fetchTimeout" value="${preload.fetchTimeout}" min="1000" max="30000" step="1000">
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-label">重试次数</label>
                            <div class="wo-config-description">
                                请求失败时的最大重试次数
                            </div>
                            <input type="number" class="wo-config-input" data-path="preload.retryAttempts" value="${preload.retryAttempts}" min="0" max="10">
                        </div>
                    </div>
                </div>
            `;
        }

        generateLayoutSection(config) {
            const layout = config.layout;
            return `
                <div class="wo-config-section">
                    <div class="wo-section-header" data-section="layout">
                        <span>📐 布局优化设置</span>
                        <span class="wo-section-toggle">▼</span>
                    </div>
                    <div class="wo-section-content" data-content="layout">
                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="layout.enabled" ${layout.enabled ? 'checked' : ''}>
                                启用布局稳定性优化
                            </label>
                            <div class="wo-config-description">
                                为无尺寸元素添加默认样式,减少布局偏移
                            </div>
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="layout.stableImages" ${layout.stableImages ? 'checked' : ''}>
                                图片稳定性优化
                            </label>
                            <div class="wo-config-description">
                                为没有明确尺寸的图片设置默认样式
                            </div>
                        </div>

                        <div class="wo-config-item">
                            <label class="wo-config-checkbox">
                                <input type="checkbox" data-path="layout.stableIframes" ${layout.stableIframes ? 'checked' : ''}>
                                iframe稳定性优化
                            </label>
                            <div class="wo-config-description">
                                为iframe设置默认的16:9比例和最小高度
                            </div>
                        </div>
                    </div>
                </div>
            `;
        }

        generateStatsSection() {
            return `
                <div class="wo-config-section">
                    <div class="wo-section-header" data-section="stats">
                        <span>📊 实时统计</span>
                        <span class="wo-section-toggle">▼</span>
                    </div>
                    <div class="wo-section-content" data-content="stats">
                        <div class="wo-stats-grid" id="wo-stats-grid">
                            <!-- 统计数据将在这里动态生成 -->
                        </div>
                        <div style="margin-top: 16px; padding-top: 16px; border-top: 1px solid #e1e5e9;">
                            <button class="wo-btn wo-btn-secondary" onclick="window.WebOptimizer.updateConfig('debug', true); console.log(window.WebOptimizer.getPerformanceReport());" style="width: 100%;">
                                📈 查看详细报告
                            </button>
                        </div>
                    </div>
                </div>
            `;
        }

        bindEvents() {
            const panel = this.configPanel;

            // 关闭按钮
            panel.querySelector('.wo-config-close').addEventListener('click', () => {
                this.hide();
            });

            // 拖拽功能
            const header = panel.querySelector('.wo-config-header');
            header.addEventListener('mousedown', (e) => this.startDrag(e));

            // 折叠/展开功能
            panel.querySelectorAll('.wo-section-header').forEach(header => {
                header.addEventListener('click', (e) => {
                    const section = e.currentTarget.dataset.section;
                    this.toggleSection(section);
                });
            });

            // 配置项监听
            panel.addEventListener('change', (e) => this.handleConfigChange(e));
            panel.addEventListener('input', debounce((e) => this.handleConfigChange(e), 500));

            // 操作按钮
            panel.querySelector('[data-action="save"]').addEventListener('click', () => this.saveConfig());
            panel.querySelector('[data-action="reset"]').addEventListener('click', () => this.resetConfig());
            panel.querySelector('[data-action="export"]').addEventListener('click', () => this.exportConfig());

            // 定期更新统计
            setInterval(() => this.updateStats(), 2000);
        }

        startDrag(e) {
            this.isDragging = true;
            const rect = this.configPanel.getBoundingClientRect();
            this.dragOffset.x = e.clientX - rect.left;
            this.dragOffset.y = e.clientY - rect.top;

            const handleMouseMove = (e) => {
                if (!this.isDragging) return;

                const x = e.clientX - this.dragOffset.x;
                const y = e.clientY - this.dragOffset.y;

                // 限制在视窗内
                const maxX = window.innerWidth - this.configPanel.offsetWidth;
                const maxY = window.innerHeight - this.configPanel.offsetHeight;

                this.configPanel.style.left = Math.max(0, Math.min(x, maxX)) + 'px';
                this.configPanel.style.top = Math.max(0, Math.min(y, maxY)) + 'px';
                this.configPanel.style.right = 'auto';
            };

            const handleMouseUp = () => {
                this.isDragging = false;
                document.removeEventListener('mousemove', handleMouseMove);
                document.removeEventListener('mouseup', handleMouseUp);
            };

            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
        }

        toggleSection(sectionName) {
            const content = this.configPanel.querySelector(`[data-content="${sectionName}"]`);
            const toggle = this.configPanel.querySelector(`[data-section="${sectionName}"] .wo-section-toggle`);

            if (content.classList.contains('collapsed')) {
                content.classList.remove('collapsed');
                toggle.classList.remove('collapsed');
                toggle.textContent = '▼';
            } else {
                content.classList.add('collapsed');
                toggle.classList.add('collapsed');
                toggle.textContent = '▶';
            }
        }

        handleConfigChange(e) {
            const path = e.target.dataset.path;
            if (!path) return;

            let value;
            if (e.target.type === 'checkbox') {
                value = e.target.checked;
            } else if (e.target.type === 'number') {
                value = parseInt(e.target.value) || 0;
            } else if (e.target.className.includes('wo-config-textarea') && (path.includes('blacklist') || path.includes('whitelist') || path.includes('globalBlacklist'))) {
                value = e.target.value.split('\n').map(line => line.trim()).filter(line => line);
            } else if (path === 'preload.types') {
                value = e.target.value.split(',').map(type => type.trim()).filter(type => type);
            } else {
                value = e.target.value;
            }

            try {
                this.configManager.set(path, value);
                this.showNotification('配置已更新', 'success');
            } catch (error) {
                this.showNotification('配置更新失败: ' + error.message, 'error');
            }
        }

        saveConfig() {
            try {
                this.configManager.saveConfig();
                this.showNotification('配置已保存到本地存储', 'success');
            } catch (error) {
                this.showNotification('保存失败: ' + error.message, 'error');
            }
        }

        resetConfig() {
            if (confirm('确定要重置为默认配置吗?这将丢失所有自定义设置。')) {
                try {
                    // 重置配置
                    this.configManager.config = deepMerge({}, this.configManager.defaultConfig);
                    this.configManager.saveConfig();

                    // 重新生成面板
                    this.configPanel.querySelector('.wo-config-content').innerHTML =
                        this.generateGeneralSection(this.configManager.config) +
                        this.generateLazyLoadSection(this.configManager.config) +
                        this.generatePreconnectSection(this.configManager.config) +
                        this.generatePreloadSection(this.configManager.config) +
                        this.generateLayoutSection(this.configManager.config) +
                        this.generateStatsSection();

                    // 重新绑定事件
                    this.bindEvents();

                    this.showNotification('配置已重置为默认值', 'success');
                } catch (error) {
                    this.showNotification('重置失败: ' + error.message, 'error');
                }
            }
        }

        exportConfig() {
            try {
                const config = JSON.stringify(this.configManager.config, null, 2);
                const blob = new Blob([config], { type: 'application/json' });
                const url = URL.createObjectURL(blob);

                const link = document.createElement('a');
                link.href = url;
                link.download = `web-optimizer-config-${new Date().toISOString().slice(0, 10)}.json`;
                link.click();

                URL.revokeObjectURL(url);
                this.showNotification('配置已导出到文件', 'success');
            } catch (error) {
                this.showNotification('导出失败: ' + error.message, 'error');
            }
        }

        updateStats() {
            if (!this.isVisible) return;

            const statsGrid = document.getElementById('wo-stats-grid');
            if (!statsGrid) return;

            try {
                const optimizer = window.WebOptimizer;
                if (!optimizer) return;

                const stats = optimizer.getPerformanceReport();
                const counters = stats.counters;

                statsGrid.innerHTML = `
                    <div class="wo-stat-item">
                        <span class="wo-stat-value">${document.querySelectorAll('img').length}</span>
                        <div class="wo-stat-label">页面图片总数</div>
                    </div>
                    <div class="wo-stat-item">
                        <span class="wo-stat-value">${counters['processed-images']}</span>
                        <div class="wo-stat-label">已处理图片</div>
                    </div>
                    <div class="wo-stat-item">
                        <span class="wo-stat-value">${counters['lazy-loaded-images']}</span>
                        <div class="wo-stat-label">懒加载图片</div>
                    </div>
                    <div class="wo-stat-item">
                        <span class="wo-stat-value">${counters['preconnected-domains']}</span>
                        <div class="wo-stat-label">预连接域名</div>
                    </div>
                    <div class="wo-stat-item">
                        <span class="wo-stat-value">${counters['preloaded-resources']}</span>
                        <div class="wo-stat-label">预加载资源</div>
                    </div>
                    <div class="wo-stat-item">
                        <span class="wo-stat-value">${stats.performance.efficiency}</span>
                        <div class="wo-stat-label">优化效率</div>
                    </div>
                `;
            } catch (error) {
                console.warn('更新统计数据失败:', error);
            }
        }

        showNotification(message, type = 'info') {
            // 创建通知元素
            const notification = document.createElement('div');
            notification.style.cssText = `
                position: fixed;
                top: 20px;
                right: 20px;
                padding: 12px 20px;
                background: ${type === 'success' ? '#48bb78' : type === 'error' ? '#f56565' : '#4299e1'};
                color: white;
                border-radius: 6px;
                font-size: 14px;
                z-index: 2147483648;
                box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
                transform: translateX(100%);
                transition: transform 0.3s ease;
            `;
            notification.textContent = message;
            document.body.appendChild(notification);

            // 显示动画
            setTimeout(() => {
                notification.style.transform = 'translateX(0)';
            }, 100);

            // 自动移除
            setTimeout(() => {
                notification.style.transform = 'translateX(100%)';
                setTimeout(() => {
                    document.body.removeChild(notification);
                }, 300);
            }, 3000);
        }

        setupKeyboardShortcut() {
            // 创建浮动按钮
            const toggleBtn = document.createElement('button');
            toggleBtn.className = 'wo-toggle-btn';
            toggleBtn.innerHTML = '⚙️';
            toggleBtn.title = '打开 Web Optimizer 配置 (Ctrl+Shift+O)';
            toggleBtn.addEventListener('click', () => this.toggle());
            document.body.appendChild(toggleBtn);

            // 键盘快捷键
            document.addEventListener('keydown', (e) => {
                if (e.ctrlKey && e.shiftKey && e.key === 'O') {
                    e.preventDefault();
                    this.toggle();
                }
            });

            // 延迟显示浮动按钮
            setTimeout(() => {
                toggleBtn.classList.remove('wo-hidden');
            }, 2000);
        }

        show() {
            this.isVisible = true;
            this.configPanel.classList.remove('wo-hidden');
            this.updateStats();
        }

        hide() {
            this.isVisible = false;
            this.configPanel.classList.add('wo-hidden');
        }

        toggle() {
            if (this.isVisible) {
                this.hide();
            } else {
                this.show();
            }
        }
    }

    // ========================
    // 配置管理系统
    // ========================

    /**
     * 配置管理器 - 使用深度合并
     */
    class ConfigManager {
        constructor() {
            this.defaultConfig = {
                debug: false,

                // 全局黑名单
                globalBlacklist: [
                    // 可以添加需要完全跳过优化的域名
                ],

                // 懒加载配置
                lazyLoad: {
                    enabled: true,
                    minSize: 100,
                    rootMargin: '200px',
                    threshold: 0.01,
                    skipHidden: true,
                    batchSize: 32,
                    blacklist: []
                },

                // 预连接配置
                preconnect: {
                    enabled: true,
                    maxConnections: 5,
                    whitelist: [
                        // CDN 和字体服务
                        'fonts.gstatic.com',
                        'fonts.googleapis.com',
                        'fonts.googleapis.cn',
                        'fonts.loli.net',

                        // 常用 CDN
                        'cdnjs.cloudflare.com',
                        'cdn.jsdelivr.net',
                        'unpkg.com',
                        'cdn.bootcdn.net',
                        'cdn.bootcss.com',
                        'libs.baidu.com',
                        'cdn.staticfile.org',

                        // 其他常用服务
                        'ajax.googleapis.com',
                        'code.jquery.com',
                        'maxcdn.bootstrapcdn.com',
                        'kit.fontawesome.com',
                        'lf3-cdn-tos.bytecdntp.com',
                        'unpkg.zhimg.com',
                        'npm.elemecdn.com',
                        'g.alicdn.com'
                    ],
                    blacklist: []
                },

                // 预加载配置
                preload: {
                    enabled: true,
                    maxPreloads: 5,
                    types: ['css', 'js', 'woff2', 'woff'],
                    fetchTimeout: 5000,
                    retryAttempts: 3,
                    blacklist: []
                },

                // 布局稳定性配置
                layout: {
                    enabled: true,
                    stableImages: true,
                    stableIframes: true,
                    blacklist: []
                }
            };

            this.config = this.loadConfig();
            this.validateConfig();
        }

        loadConfig() {
            try {
                const saved = GM_getValue('optimizer_config_v2', null);
                if (saved) {
                    // 使用深度合并替代浅合并
                    return deepMerge(this.defaultConfig, JSON.parse(saved));
                }
            } catch (e) {
                console.warn('[配置] 加载用户配置失败,使用默认配置', e);
            }
            return deepMerge({}, this.defaultConfig);
        }

        saveConfig() {
            try {
                GM_setValue('optimizer_config_v2', JSON.stringify(this.config));
            } catch (e) {
                console.warn('[配置] 保存配置失败', e);
            }
        }

        validateConfig() {
            // 基本类型验证
            if (typeof this.config.debug !== 'boolean') {
                this.config.debug = this.defaultConfig.debug;
            }

            // 确保数组类型配置正确
            ['globalBlacklist'].forEach(key => {
                if (!Array.isArray(this.config[key])) {
                    this.config[key] = [...this.defaultConfig[key]];
                }
            });

            // 验证子配置
            ['lazyLoad', 'preconnect', 'preload', 'layout'].forEach(module => {
                if (!this.config[module] || typeof this.config[module] !== 'object') {
                    this.config[module] = deepMerge({}, this.defaultConfig[module]);
                }
            });
        }

        get(path) {
            const keys = path.split('.');
            let value = this.config;
            for (const key of keys) {
                value = value?.[key];
                if (value === undefined) break;
            }
            return value;
        }

        set(path, value) {
            const keys = path.split('.');
            const lastKey = keys.pop();
            let target = this.config;

            for (const key of keys) {
                if (!target[key] || typeof target[key] !== 'object') {
                    target[key] = {};
                }
                target = target[key];
            }

            target[lastKey] = value;
            this.saveConfig();
        }

        isBlacklisted(hostname, module = null) {
            // 检查全局黑名单
            if (this.config.globalBlacklist.some(domain => hostname.includes(domain))) {
                return true;
            }

            // 检查模块特定黑名单
            if (module && this.config[module]?.blacklist) {
                return this.config[module].blacklist.some(domain => hostname.includes(domain));
            }

            return false;
        }
    }

    // ========================
    // 核心优化模块
    // ========================

    /**
     * 懒加载管理器 - 增强类型检查
     */
    class LazyLoadManager {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.observer = null;
            this.mutationObserver = null;
            this.processedImages = new Set();
            this.pendingImages = [];
            this.batchScheduled = false;
            this.processedElements = new WeakSet(); // 避免重复处理
        }

        init() {
            if (!this.config.get('lazyLoad.enabled')) {
                this.monitor.log('懒加载功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'lazyLoad')) {
                this.monitor.log('当前站点在懒加载黑名单中');
                return;
            }

            this.monitor.start('lazyLoad-init');
            this.setupIntersectionObserver();
            this.processExistingImages();
            this.setupMutationObserver();
            this.monitor.end('lazyLoad-init');
        }

        setupIntersectionObserver() {
            if (!('IntersectionObserver' in window)) {
                this.monitor.warn('浏览器不支持 IntersectionObserver,使用兼容模式');
                this.setupFallbackMode();
                return;
            }

            this.observer = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        this.restoreImage(entry.target);
                        this.observer.unobserve(entry.target);
                        this.monitor.count('lazy-loaded-images');
                    }
                });
            }, {
                rootMargin: this.config.get('lazyLoad.rootMargin'),
                threshold: this.config.get('lazyLoad.threshold')
            });
        }

        setupFallbackMode() {
            const checkVisible = throttle(() => {
                const images = document.querySelectorAll('img[data-lazy-src]');
                const margin = parseInt(this.config.get('lazyLoad.rootMargin')) || 200;

                images.forEach(img => {
                    const rect = img.getBoundingClientRect();
                    if (rect.top < window.innerHeight + margin) {
                        this.restoreImage(img);
                    }
                });
            }, 200);

            window.addEventListener('scroll', checkVisible, { passive: true });
            window.addEventListener('resize', checkVisible, { passive: true });
            checkVisible();
        }

        isLazyCandidate(img) {
            // 基本检查 - 使用更严格的类型检查
            if (!isImageElement(img)) return false;
            if (this.processedElements.has(img)) return false;
            if (img.hasAttribute('data-lazy-processed')) return false;
            if (img.loading === 'eager') return false;
            if (img.complete && img.src) return false;
            if (img.src && img.src.startsWith('data:')) return false;

            // 跳过已有懒加载的图片
            if (img.hasAttribute('data-src') || img.hasAttribute('data-srcset')) return false;

            // 尺寸检查
            const minSize = this.config.get('lazyLoad.minSize');
            const rect = img.getBoundingClientRect();
            if (rect.width < minSize || rect.height < minSize) return false;

            // 可见性检查
            if (this.config.get('lazyLoad.skipHidden') && !isElementVisible(img)) {
                return false;
            }

            return true;
        }

        processImage(img) {
            if (!this.isLazyCandidate(img)) return false;

            // 标记为已处理
            this.processedElements.add(img);
            img.setAttribute('data-lazy-processed', 'true');

            // 设置原生懒加载(如果支持)
            if ('loading' in HTMLImageElement.prototype) {
                img.loading = 'lazy';
            }

            // 保存原始 src
            if (img.src) {
                img.setAttribute('data-lazy-src', img.src);
                img.removeAttribute('src');
            }
            if (img.srcset) {
                img.setAttribute('data-lazy-srcset', img.srcset);
                img.removeAttribute('srcset');
            }

            // 添加到观察者
            if (this.observer) {
                this.observer.observe(img);
            }

            this.processedImages.add(img);
            this.monitor.count('processed-images');
            return true;
        }

        restoreImage(img) {
            const src = img.getAttribute('data-lazy-src');
            const srcset = img.getAttribute('data-lazy-srcset');

            if (src) {
                img.src = src;
                img.removeAttribute('data-lazy-src');
            }
            if (srcset) {
                img.srcset = srcset;
                img.removeAttribute('data-lazy-srcset');
            }

            this.processedImages.delete(img);
        }

        batchProcess(images) {
            const batchSize = this.config.get('lazyLoad.batchSize');
            let processed = 0;

            const processBatch = () => {
                const end = Math.min(processed + batchSize, images.length);

                for (let i = processed; i < end; i++) {
                    this.processImage(images[i]);
                }

                processed = end;

                if (processed < images.length) {
                    (window.requestIdleCallback || window.requestAnimationFrame)(processBatch);
                } else {
                    this.monitor.log(`懒加载处理完成,共处理 ${processed} 张图片`);
                }
            };

            processBatch();
        }

        processExistingImages() {
            const images = Array.from(document.querySelectorAll('img'));
            this.monitor.log(`发现 ${images.length} 张图片,开始批量处理`);
            this.batchProcess(images);
        }

        // 改进的批处理调度 - 更好的并发控制
        scheduleBatchProcess() {
            if (this.batchScheduled || this.pendingImages.length === 0) return;

            this.batchScheduled = true;
            (window.requestIdleCallback || window.requestAnimationFrame)(() => {
                const images = [...this.pendingImages];
                this.pendingImages = [];
                this.batchScheduled = false;

                let processedCount = 0;
                images.forEach(img => {
                    if (this.processImage(img)) {
                        processedCount++;
                    }
                });

                if (processedCount > 0) {
                    this.monitor.log(`动态处理 ${processedCount} 张新图片`);
                }
            });
        }

        setupMutationObserver() {
            let pendingMutations = [];
            let processingScheduled = false;

            const processMutations = () => {
                const mutations = [...pendingMutations];
                pendingMutations = [];
                processingScheduled = false;

                mutations.forEach(mutation => {
                    // 处理新增节点
                    mutation.addedNodes.forEach(node => {
                        if (isImageElement(node)) {
                            this.pendingImages.push(node);
                        } else if (node.querySelectorAll) {
                            const images = node.querySelectorAll('img');
                            this.pendingImages.push(...Array.from(images));
                        }
                    });

                    // 清理移除的节点
                    mutation.removedNodes.forEach(node => {
                        if (isImageElement(node) && this.observer) {
                            this.observer.unobserve(node);
                            this.processedImages.delete(node);
                            this.processedElements.delete && this.processedElements.delete(node);
                        }
                    });
                });

                this.scheduleBatchProcess();
            };

            this.mutationObserver = new MutationObserver((mutations) => {
                pendingMutations.push(...mutations);

                if (!processingScheduled) {
                    processingScheduled = true;
                    (window.requestIdleCallback || window.requestAnimationFrame)(processMutations);
                }
            });

            this.mutationObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        destroy() {
            if (this.observer) {
                this.observer.disconnect();
                this.observer = null;
            }
            if (this.mutationObserver) {
                this.mutationObserver.disconnect();
                this.mutationObserver = null;
            }

            // 恢复所有处理过的图片
            this.processedImages.forEach(img => this.restoreImage(img));
            this.processedImages.clear();
        }
    }

    /**
     * 预加载管理器 - 改进异步处理
     */
    class PreloadManager {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.preloaded = new LRUCache(this.config.get('preload.maxPreloads'));
            this.cssCache = new LRUCache(50);
            this.mutationObserver = null;
        }

        async init() {
            if (!this.config.get('preload.enabled')) {
                this.monitor.log('预加载功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'preload')) {
                this.monitor.log('当前站点在预加载黑名单中');
                return;
            }

            this.monitor.start('preload-init');
            await this.scanExistingResources(); // 改为异步
            this.setupMutationObserver();
            this.monitor.end('preload-init');
        }

        getResourceType(url) {
            const ext = url.split('.').pop()?.toLowerCase();
            const types = this.config.get('preload.types');

            if (!types.includes(ext)) return null;

            switch (ext) {
                case 'css': return 'style';
                case 'js': return 'script';
                case 'woff':
                case 'woff2':
                case 'ttf':
                case 'otf': return 'font';
                default: return null;
            }
        }

        doPreload(url, asType) {
            if (this.preloaded.has(url) || this.preloaded.size >= this.config.get('preload.maxPreloads')) {
                return false;
            }

            try {
                const link = document.createElement('link');
                link.rel = 'preload';
                link.as = asType;
                link.href = url;

                if (asType === 'font') {
                    link.crossOrigin = 'anonymous';
                    // 设置正确的 MIME 类型
                    if (url.includes('.woff2')) link.type = 'font/woff2';
                    else if (url.includes('.woff')) link.type = 'font/woff';
                    else if (url.includes('.ttf')) link.type = 'font/ttf';
                    else if (url.includes('.otf')) link.type = 'font/otf';
                }

                document.head.appendChild(link);
                this.preloaded.set(url, true);
                this.monitor.log(`预加载 ${asType}: ${url}`);
                this.monitor.count('preloaded-resources');
                return true;
            } catch (e) {
                this.monitor.warn(`预加载失败: ${url}`, e);
                return false;
            }
        }

        async extractFontsFromCSS(cssUrl) {
            if (this.cssCache.has(cssUrl)) {
                return this.cssCache.get(cssUrl);
            }

            const operation = async () => {
                const controller = new AbortController();
                const timeoutId = setTimeout(() => controller.abort(), this.config.get('preload.fetchTimeout'));

                try {
                    const response = await fetch(cssUrl, {
                        signal: controller.signal,
                        mode: 'cors',
                        credentials: 'omit'
                    });

                    clearTimeout(timeoutId);

                    if (!response.ok) throw new Error(`HTTP ${response.status}`);

                    const text = await response.text();
                    const fontUrls = [];
                    const fontRegex = /url\(["']?([^")']+\.(woff2?|ttf|otf))["']?\)/gi;
                    let match;

                    while ((match = fontRegex.exec(text)) !== null) {
                        const fontUrl = safeParseURL(match[1], cssUrl);
                        if (fontUrl) {
                            fontUrls.push(fontUrl.href);
                        }
                    }

                    this.cssCache.set(cssUrl, fontUrls);
                    return fontUrls;
                } finally {
                    clearTimeout(timeoutId);
                }
            };

            try {
                // 使用重试机制
                return await RetryableOperation.executeWithRetry(
                    operation,
                    this.config.get('preload.retryAttempts')
                );
            } catch (e) {
                this.monitor.warn(`提取字体失败: ${cssUrl}`, e.message);
                this.cssCache.set(cssUrl, []);
                return [];
            }
        }

        // 改进的异步资源扫描 - 更好的并发控制
        async scanExistingResources() {
            // 处理 CSS 文件
            const cssLinks = Array.from(document.querySelectorAll('link[rel="stylesheet"][href]'));
            const jsScripts = Array.from(document.querySelectorAll('script[src]'));

            // 处理 CSS 文件的 Promise 数组
            const cssPromises = cssLinks.map(async link => {
                const cssUrl = link.href;
                const asType = this.getResourceType(cssUrl);

                if (asType === 'style') {
                    this.doPreload(cssUrl, asType);

                    // 异步提取和预加载字体
                    try {
                        const fontUrls = await this.extractFontsFromCSS(cssUrl);
                        fontUrls.forEach(fontUrl => {
                            const fontType = this.getResourceType(fontUrl);
                            if (fontType === 'font') {
                                this.doPreload(fontUrl, fontType);
                            }
                        });
                    } catch (e) {
                        // 忽略字体提取错误,不影响主流程
                        this.monitor.warn(`CSS处理失败: ${cssUrl}`, e);
                    }
                }
            });

            // 处理 JS 文件
            jsScripts.forEach(script => {
                const asType = this.getResourceType(script.src);
                if (asType === 'script') {
                    this.doPreload(script.src, asType);
                }
            });

            // 等待所有 CSS 处理完成,但不阻塞初始化
            try {
                await Promise.allSettled(cssPromises);
                this.monitor.log(`资源扫描完成,处理了 ${cssLinks.length} 个CSS文件和 ${jsScripts.length} 个JS文件`);
            } catch (e) {
                this.monitor.warn('资源扫描过程中出现错误', e);
            }
        }

        setupMutationObserver() {
            this.mutationObserver = new MutationObserver(debounce(async (mutations) => {
                const newCSSLinks = [];
                const newJSScripts = [];

                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.tagName === 'LINK' && node.rel === 'stylesheet' && node.href) {
                            newCSSLinks.push(node);
                        } else if (node.tagName === 'SCRIPT' && node.src) {
                            newJSScripts.push(node);
                        }
                    });
                });

                // 异步处理新添加的资源
                if (newCSSLinks.length > 0 || newJSScripts.length > 0) {
                    const promises = newCSSLinks.map(async node => {
                        const asType = this.getResourceType(node.href);
                        if (asType === 'style') {
                            this.doPreload(node.href, asType);

                            // 异步处理字体
                            try {
                                const fontUrls = await this.extractFontsFromCSS(node.href);
                                fontUrls.forEach(fontUrl => {
                                    const fontType = this.getResourceType(fontUrl);
                                    if (fontType === 'font') {
                                        this.doPreload(fontUrl, fontType);
                                    }
                                });
                            } catch (e) {
                                // 忽略错误
                            }
                        }
                    });

                    newJSScripts.forEach(node => {
                        const asType = this.getResourceType(node.src);
                        if (asType === 'script') {
                            this.doPreload(node.src, asType);
                        }
                    });

                    // 不等待 Promise 完成,避免阻塞
                    Promise.allSettled(promises).then(() => {
                        this.monitor.log(`动态处理了 ${newCSSLinks.length} 个CSS和 ${newJSScripts.length} 个JS`);
                    });
                }
            }, 200));

            this.mutationObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        destroy() {
            if (this.mutationObserver) {
                this.mutationObserver.disconnect();
                this.mutationObserver = null;
            }
            this.preloaded.clear();
            this.cssCache.clear();
        }
    }

    // 其他管理器类保持不变,仅引用已改进的配置和监控器
    class PreconnectManager {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.connected = new LRUCache(this.config.get('preconnect.maxConnections'));
            this.mutationObserver = null;
        }

        init() {
            if (!this.config.get('preconnect.enabled')) {
                this.monitor.log('预连接功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'preconnect')) {
                this.monitor.log('当前站点在预连接黑名单中');
                return;
            }

            this.monitor.start('preconnect-init');
            this.scanExistingResources();
            this.setupMutationObserver();
            this.monitor.end('preconnect-init');
        }

        shouldPreconnect(hostname) {
            if (!hostname || hostname === location.hostname) return false;
            if (this.connected.has(hostname)) return false;

            const whitelist = this.config.get('preconnect.whitelist');
            return whitelist.some(domain => hostname.endsWith(domain));
        }

        doPreconnect(hostname) {
            if (!this.shouldPreconnect(hostname)) return false;

            try {
                const link = document.createElement('link');
                link.rel = 'preconnect';
                link.href = `https://${hostname}`;
                link.crossOrigin = 'anonymous';
                document.head.appendChild(link);

                this.connected.set(hostname, true);
                this.monitor.log(`预连接: ${hostname}`);
                this.monitor.count('preconnected-domains');
                return true;
            } catch (e) {
                this.monitor.warn(`预连接失败: ${hostname}`, e);
                return false;
            }
        }

        extractHostnames(elements) {
            const hostnames = new Set();

            elements.forEach(el => {
                const url = safeParseURL(el.src || el.href);
                if (url && url.hostname !== location.hostname) {
                    hostnames.add(url.hostname);
                }
            });

            return Array.from(hostnames);
        }

        scanExistingResources() {
            const selectors = [
                'script[src]',
                'link[href]',
                'img[src]',
                'audio[src]',
                'video[src]',
                'source[src]'
            ];

            const elements = document.querySelectorAll(selectors.join(','));
            const hostnames = this.extractHostnames(elements);

            let connected = 0;
            hostnames.forEach(hostname => {
                if (this.doPreconnect(hostname)) {
                    connected++;
                }
            });

            this.monitor.log(`扫描完成,预连接 ${connected} 个域名`);
        }

        setupMutationObserver() {
            this.mutationObserver = new MutationObserver(debounce((mutations) => {
                const newElements = [];

                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.src || node.href) {
                            newElements.push(node);
                        } else if (node.querySelectorAll) {
                            const elements = node.querySelectorAll('script[src], link[href], img[src]');
                            newElements.push(...elements);
                        }
                    });
                });

                if (newElements.length > 0) {
                    const hostnames = this.extractHostnames(newElements);
                    hostnames.forEach(hostname => this.doPreconnect(hostname));
                }
            }, 200));

            this.mutationObserver.observe(document.body, {
                childList: true,
                subtree: true
            });
        }

        destroy() {
            if (this.mutationObserver) {
                this.mutationObserver.disconnect();
                this.mutationObserver = null;
            }
            this.connected.clear();
        }
    }

    class LayoutStabilizer {
        constructor(config, monitor) {
            this.config = config;
            this.monitor = monitor;
            this.injectedStyle = null;
        }

        init() {
            if (!this.config.get('layout.enabled')) {
                this.monitor.log('布局优化功能已禁用');
                return;
            }

            if (this.config.isBlacklisted(location.hostname, 'layout')) {
                this.monitor.log('当前站点在布局优化黑名单中');
                return;
            }

            this.monitor.start('layout-init');
            this.injectStabilizationStyles();
            this.monitor.end('layout-init');
        }

        generateCSS() {
            const styles = [];

            if (this.config.get('layout.stableImages')) {
                styles.push(`
                    /* 图片布局稳定性优化 */
                    img:not([width]):not([height]):not([style*="width"]):not([style*="height"]) {
                        min-height: 1px;
                        // max-width: 100%;
                        // height: auto;
                    }

                    /* 现代浏览器的 aspect-ratio 支持 */
                    @supports (aspect-ratio: 1/1) {
                        img[width][height]:not([style*="aspect-ratio"]) {
                            aspect-ratio: attr(width) / attr(height);
                        }
                    }
                `);
            }

            if (this.config.get('layout.stableIframes')) {
                styles.push(`
                    /* iframe 布局稳定性优化 */
                    iframe:not([width]):not([height]):not([style*="width"]):not([style*="height"]) {
                        // width: 100%;
                        // height: auto;
                        min-height: 1px;
                    }

                    @supports (aspect-ratio: 16/9) {
                        iframe:not([style*="aspect-ratio"]) {
                            aspect-ratio: 16/9;
                        }
                    }
                `);
            }

            return styles.join('\n');
        }

        injectStabilizationStyles() {
            const css = this.generateCSS().trim();
            if (!css) return;

            try {
                this.injectedStyle = document.createElement('style');
                this.injectedStyle.setAttribute('data-optimizer', 'layout-stabilizer');
                this.injectedStyle.textContent = css;

                // 优先插入到 head,如果不存在则插入到 document
                const target = document.head || document.documentElement;
                target.appendChild(this.injectedStyle);

                this.monitor.log('布局稳定性样式已注入');
            } catch (e) {
                this.monitor.warn('注入布局样式失败', e);
            }
        }

        destroy() {
            if (this.injectedStyle && this.injectedStyle.parentNode) {
                this.injectedStyle.parentNode.removeChild(this.injectedStyle);
                this.injectedStyle = null;
                this.monitor.log('布局样式已移除');
            }
        }
    }

    // ========================
    // 主优化器
    // ========================

    /**
     * 主优化器类 - v2.0
     */
    class WebOptimizer {
        constructor() {
            this.config = new ConfigManager();
            this.monitor = new PerformanceMonitor(this.config.get('debug'));

            // 优化模块
            this.modules = {
                lazyLoad: new LazyLoadManager(this.config, this.monitor),
                preconnect: new PreconnectManager(this.config, this.monitor),
                preload: new PreloadManager(this.config, this.monitor),
                layout: new LayoutStabilizer(this.config, this.monitor)
            };

            this.initialized = false;
            this.cleanupTasks = [];

            // v2.0 新增:可视化配置界面
            this.visualConfig = null;
        }

        async init() {
            if (this.initialized) return;

            this.monitor.start('total-init');
            this.monitor.log('Web Optimizer Enhanced v2.0 开始初始化');

            // 检查全局黑名单
            if (this.config.isBlacklisted(location.hostname)) {
                this.monitor.log('当前站点在全局黑名单中,跳过所有优化');
                return;
            }

            try {
                // 等待 DOM 基本可用
                if (document.readyState === 'loading') {
                    await new Promise(resolve => {
                        document.addEventListener('DOMContentLoaded', resolve, { once: true });
                    });
                }

                // 初始化各个模块 - 改进的错误隔离
                const initPromises = Object.entries(this.modules).map(async ([name, module]) => {
                    try {
                        this.monitor.start(`init-${name}`);
                        await module.init();
                        this.monitor.end(`init-${name}`);
                        return { name, success: true };
                    } catch (e) {
                        this.monitor.error(`模块 ${name} 初始化失败`, e);
                        return { name, success: false, error: e };
                    }
                });

                const results = await Promise.allSettled(initPromises);
                const successCount = results.filter(r => r.status === 'fulfilled' && r.value.success).length;
                this.monitor.log(`模块初始化完成,成功: ${successCount}/${Object.keys(this.modules).length}`);

                // 设置清理任务
                this.setupCleanupTasks();

                // v2.0 新增:初始化可视化配置界面
                this.initVisualConfig();

                this.initialized = true;
                this.monitor.end('total-init');
                this.monitor.log('Web Optimizer Enhanced v2.0 初始化完成');

                // 显示初始化报告
                this.showInitReport();

            } catch (e) {
                this.monitor.error('初始化失败', e);
            }
        }

        // v2.0 新增:初始化可视化配置界面
        initVisualConfig() {
            try {
                // 延迟初始化,确保页面稳定
                setTimeout(() => {
                    this.visualConfig = new VisualConfigManager(this.config);
                }, 1000);
            } catch (e) {
                this.monitor.warn('可视化配置界面初始化失败', e);
            }
        }

        setupCleanupTasks() {
            // 定期清理缓存
            const cleanupInterval = setInterval(() => {
                Object.values(this.modules).forEach(module => {
                    if (module.cssCache) module.cssCache.clear();
                    if (module.connected) module.connected.clear();
                    if (module.preloaded) module.preloaded.clear();
                });
                this.monitor.log('定期清理完成');
            }, 10 * 60 * 1000); // 10分钟

            this.cleanupTasks.push(() => clearInterval(cleanupInterval));

            // 页面卸载时清理
            const cleanup = () => {
                this.destroy();
            };

            window.addEventListener('beforeunload', cleanup);
            this.cleanupTasks.push(() => {
                window.removeEventListener('beforeunload', cleanup);
            });
        }

        showInitReport() {
            if (!this.config.get('debug')) return;

            console.groupCollapsed('[Web Optimizer Enhanced v2.0] 初始化报告');
            console.log('版本: 2.0');
            console.log('当前域名:', location.hostname);
            console.log('启用的功能:', Object.entries(this.config.config)
                .filter(([key, value]) => typeof value === 'object' && value.enabled)
                .map(([key]) => key)
            );

            // 显示性能计数器
            console.log('性能计数:', {
                'processed-images': this.monitor.getCounter('processed-images'),
                'lazy-loaded-images': this.monitor.getCounter('lazy-loaded-images'),
                'preconnected-domains': this.monitor.getCounter('preconnected-domains'),
                'preloaded-resources': this.monitor.getCounter('preloaded-resources')
            });

            console.log('配置详情:', this.config.config);
            console.log('💡 提示: 按 Ctrl+Shift+O 打开可视化配置界面');
            console.groupEnd();
        }

        destroy() {
            if (!this.initialized) return;

            this.monitor.log('开始清理资源');

            // 清理各个模块
            Object.values(this.modules).forEach(module => {
                if (module.destroy) {
                    try {
                        module.destroy();
                    } catch (e) {
                        this.monitor.warn('模块清理失败', e);
                    }
                }
            });

            // 执行清理任务
            this.cleanupTasks.forEach(task => {
                try {
                    task();
                } catch (e) {
                    this.monitor.warn('清理任务执行失败', e);
                }
            });
            this.cleanupTasks = [];

            this.initialized = false;
            this.monitor.log('资源清理完成');
        }

        // 公共 API - 增强版
        updateConfig(path, value) {
            this.config.set(path, value);
            this.monitor.log(`配置已更新: ${path} = ${value}`);

            // 如果是调试模式变更,更新监控器
            if (path === 'debug') {
                this.monitor.debug = value;
            }
        }

        getStats() {
            return {
                initialized: this.initialized,
                version: '2.0',
                hostname: location.hostname,
                config: this.config.config,
                modules: Object.keys(this.modules),
                counters: {
                    'processed-images': this.monitor.getCounter('processed-images'),
                    'lazy-loaded-images': this.monitor.getCounter('lazy-loaded-images'),
                    'preconnected-domains': this.monitor.getCounter('preconnected-domains'),
                    'preloaded-resources': this.monitor.getCounter('preloaded-resources')
                }
            };
        }

        // 新增:性能报告
        getPerformanceReport() {
            const stats = this.getStats();
            const imageStats = {
                total: document.querySelectorAll('img').length,
                processed: stats.counters['processed-images'],
                lazyLoaded: stats.counters['lazy-loaded-images']
            };

            return {
                ...stats,
                performance: {
                    images: imageStats,
                    domains: stats.counters['preconnected-domains'],
                    resources: stats.counters['preloaded-resources'],
                    efficiency: imageStats.total > 0 ? (imageStats.processed / imageStats.total * 100).toFixed(1) + '%' : '0%'
                }
            };
        }

        // v2.0 新增:打开/关闭配置界面
        openConfig() {
            if (this.visualConfig) {
                this.visualConfig.show();
            }
        }

        closeConfig() {
            if (this.visualConfig) {
                this.visualConfig.hide();
            }
        }

        toggleConfig() {
            if (this.visualConfig) {
                this.visualConfig.toggle();
            }
        }
    }

    // ========================
    // 全局初始化
    // ========================

    // 创建全局实例
    const optimizer = new WebOptimizer();

    // 暴露到全局作用域(调试用)
    if (typeof window !== 'undefined') {
        window.WebOptimizer = optimizer;

        // v2.0 新增:暴露工具函数供调试使用
        window.WebOptimizerUtils = {
            debounce,
            throttle,
            safeParseURL,
            isElementVisible,
            deepMerge,
            delay,
            RetryableOperation
        };
    }

    // 启动优化器
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => optimizer.init());
    } else {
        // 延迟一点时间,确保页面基本稳定
        setTimeout(() => optimizer.init(), 100);
    }

})();