Ultimate Web Optimizer

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

目前為 2025-06-10 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

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

})();