// ==UserScript== // @name 网页加速器专业版 // @namespace https://docs.scriptcat.org/ // @version 3.0.0 // @description 智能预加载和缓存网页,显著提升浏览速度 // @author HyperNav // @match https://*/* // @match http://*/* // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_listValues // @grant GM_registerMenuCommand // @grant GM_notification // @noframes // @icon https://img.icons8.com/color/96/000000/rocket.png // @run-at document-start // ==/UserScript== (function() { 'use strict'; // 确保只运行一次 if (window.hypernavLoaded) return; window.hypernavLoaded = true; // 创建样式 const style = document.createElement('style'); style.textContent = ` .hypernav-container { all: initial; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-size: 12px; z-index: 2147483647; } .hypernav-toggle-btn { position: fixed; bottom: 20px; right: 20px; width: 48px; height: 48px; border-radius: 50%; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 20px rgba(102, 126, 234, 0.5); transition: all 0.3s ease; z-index: 2147483646; } .hypernav-toggle-btn:hover { transform: scale(1.1); box-shadow: 0 6px 30px rgba(102, 126, 234, 0.7); } .hypernav-panel { position: fixed; bottom: 80px; right: 20px; width: 350px; background: white; border-radius: 12px; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2); overflow: hidden; z-index: 2147483645; opacity: 0; transform: translateY(20px); transition: all 0.3s ease; } .hypernav-panel.show { opacity: 1; transform: translateY(0); } .hypernav-header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 20px; display: flex; justify-content: space-between; align-items: center; } .hypernav-title { display: flex; align-items: center; gap: 10px; } .hypernav-title h3 { margin: 0; font-size: 16px; font-weight: 600; } .hypernav-badge { background: rgba(255, 255, 255, 0.2); padding: 2px 8px; border-radius: 10px; font-size: 10px; } .hypernav-close-btn { background: none; border: none; color: white; cursor: pointer; font-size: 20px; line-height: 1; padding: 5px; border-radius: 4px; } .hypernav-close-btn:hover { background: rgba(255, 255, 255, 0.2); } .hypernav-content { padding: 20px; max-height: 400px; overflow-y: auto; } .hypernav-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin-bottom: 20px; } .hypernav-stat { background: #f5f5f5; padding: 10px; border-radius: 8px; text-align: center; } .hypernav-stat-value { font-size: 20px; font-weight: 700; margin-bottom: 4px; } .hypernav-stat-label { font-size: 11px; color: #666; } .hypernav-network-status { display: flex; align-items: center; gap: 8px; padding: 10px; background: #f0f7ff; border-radius: 8px; margin-bottom: 20px; } .hypernav-network-indicator { width: 8px; height: 8px; border-radius: 50%; } .hypernav-network-good { background: #4caf50; } .hypernav-network-medium { background: #ff9800; } .hypernav-network-poor { background: #f44336; } .hypernav-controls { margin-bottom: 20px; } .hypernav-control-group { margin-bottom: 15px; } .hypernav-control-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; } .hypernav-switch { position: relative; display: inline-block; width: 40px; height: 20px; } .hypernav-switch input { opacity: 0; width: 0; height: 0; } .hypernav-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; transition: .4s; border-radius: 20px; } .hypernav-slider:before { position: absolute; content: ""; height: 16px; width: 16px; left: 2px; bottom: 2px; background-color: white; transition: .4s; border-radius: 50%; } .hypernav-switch input:checked + .hypernav-slider { background-color: #667eea; } .hypernav-switch input:checked + .hypernav-slider:before { transform: translateX(20px); } .hypernav-select { padding: 6px 10px; border: 1px solid #ddd; border-radius: 6px; background: white; font-size: 12px; min-width: 120px; } .hypernav-slider-container { display: flex; align-items: center; gap: 10px; } .hypernav-range { width: 100px; } .hypernav-range-value { min-width: 40px; text-align: right; } .hypernav-buttons { display: flex; gap: 10px; } .hypernav-btn { flex: 1; padding: 10px; border: none; border-radius: 8px; background: #f5f5f5; color: #333; cursor: pointer; font-size: 12px; transition: all 0.2s; } .hypernav-btn:hover { background: #e5e5e5; } .hypernav-btn-primary { background: #667eea; color: white; } .hypernav-btn-primary:hover { background: #5a6fd8; } .hypernav-footer { padding: 15px 20px; background: #f9f9f9; border-top: 1px solid #eee; text-align: center; color: #666; font-size: 11px; } .hypernav-drag-handle { position: absolute; top: 0; left: 0; right: 0; height: 30px; cursor: move; } .hypernav-log { font-size: 10px; color: #999; margin-top: 5px; } .hypernav-tab-container { display: flex; border-bottom: 1px solid #eee; margin-bottom: 20px; } .hypernav-tab { padding: 10px 20px; cursor: pointer; border-bottom: 2px solid transparent; } .hypernav-tab.active { border-bottom-color: #667eea; color: #667eea; font-weight: 600; } .hypernav-tab-content { display: none; } .hypernav-tab-content.active { display: block; } .hypernav-log-entry { padding: 8px; border-bottom: 1px solid #eee; font-family: 'Courier New', monospace; font-size: 11px; } .hypernav-log-entry.success { color: #4caf50; } .hypernav-log-entry.warning { color: #ff9800; } .hypernav-log-entry.error { color: #f44336; } .hypernav-cache-list { max-height: 200px; overflow-y: auto; } .hypernav-cache-item { padding: 8px; border-bottom: 1px solid #eee; font-size: 11px; display: flex; justify-content: space-between; } .hypernav-cache-url { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 200px; } .hypernav-cache-size { color: #666; } .hypernav-speed-badge { position: absolute; top: -5px; right: -5px; background: #ff4757; color: white; border-radius: 10px; padding: 2px 6px; font-size: 10px; font-weight: bold; } .hypernav-loading { display: inline-block; width: 12px; height: 12px; border: 2px solid #f3f3f3; border-top: 2px solid #667eea; border-radius: 50%; animation: hypernav-spin 1s linear infinite; } @keyframes hypernav-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `; document.head.appendChild(style); // 主类 class HyperNav { constructor() { this.config = { enabled: true, mode: 'balanced', // conservative, balanced, aggressive prefetchMethod: 'viewport', // viewport, hover, all maxConcurrent: 3, delay: 150, threshold: 0.3, timeout: 3000, cacheDuration: 5 * 60 * 1000, // 5分钟 learnBehavior: true, showUI: true, debug: false, ignoreExternal: false }; this.state = { initialized: false, active: false, linksObserved: 0, linksPrefetched: 0, cacheHits: 0, totalLinks: 0, cache: new Map(), observer: null, uiVisible: false, sessionStart: Date.now(), performance: { baseLoadTime: 0, improvedLoadTime: 0, speedups: [] }, activePrefetches: 0 }; this.ui = { container: null, panel: null, updateInterval: null }; this.ignorePatterns = [ /\.(jpg|jpeg|png|gif|webp|svg|ico|mp4|mp3|pdf|zip|rar)$/i, /logout|signout|delete|remove|checkout|payment/i, /\/api\//i, /^javascript:/i, /^mailto:/i, /^tel:/i, /^#/i ]; this.preloadQueue = []; this.init(); } init() { this.loadConfig(); // 监听页面加载 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => this.onDOMLoaded()); } else { this.onDOMLoaded(); } this.state.initialized = true; this.log('HyperNav 初始化完成'); } onDOMLoaded() { this.createUI(); this.setupEventListeners(); if (this.config.enabled) { this.start(); } // 记录基线加载时间 this.state.performance.baseLoadTime = performance.now(); // 为Tampermonkey添加菜单 this.setupTampermonkeyMenu(); } loadConfig() { try { if (typeof GM_getValue === 'function') { const saved = GM_getValue('hypernav-config'); if (saved) { Object.assign(this.config, JSON.parse(saved)); } } else { const saved = localStorage.getItem('hypernav-config'); if (saved) { Object.assign(this.config, JSON.parse(saved)); } } } catch (e) { console.warn('加载配置失败:', e); } } saveConfig() { try { const configStr = JSON.stringify(this.config); if (typeof GM_setValue === 'function') { GM_setValue('hypernav-config', configStr); } else { localStorage.setItem('hypernav-config', configStr); } } catch (e) { console.warn('保存配置失败:', e); } } setupTampermonkeyMenu() { if (typeof GM_registerMenuCommand !== 'function') return; GM_registerMenuCommand('🚀 显示/隐藏控制面板', () => { this.ui.panel.classList.toggle('show'); }); GM_registerMenuCommand('⚡ 启用/禁用加速', () => { this.toggleEnabled(); }); GM_registerMenuCommand('📊 显示统计信息', () => { const stats = this.getStats(); if (typeof GM_notification === 'function') { GM_notification({ text: `观察链接: ${stats.linksObserved}\n预取成功: ${stats.linksPrefetched}\n加速效果: ${stats.speedImprovement}`, title: 'HyperNav 统计', timeout: 3000 }); } else { alert(JSON.stringify(stats, null, 2)); } }); GM_registerMenuCommand('🧹 清空缓存', () => { this.clearCache(); }); } createUI() { if (!this.config.showUI) return; // 创建容器 this.ui.container = document.createElement('div'); this.ui.container.className = 'hypernav-container'; document.body.appendChild(this.ui.container); // 创建切换按钮 const toggleBtn = document.createElement('button'); toggleBtn.className = 'hypernav-toggle-btn'; toggleBtn.innerHTML = '🚀'; toggleBtn.title = '网页加速器控制面板 (Ctrl+Shift+H)'; this.ui.container.appendChild(toggleBtn); // 创建控制面板 this.ui.panel = document.createElement('div'); this.ui.panel.className = 'hypernav-panel'; this.ui.panel.innerHTML = `

🚀 网页加速器

v3.0.0
控制台
缓存
日志
0
观察链接
0
已预取
0
缓存命中
0%
加速效果
网络状态: 检测中...
启用加速
工作模式
预取方式
智能学习
并发数量
3
预取延迟
150ms
忽略外部链接
缓存条目: 0
缓存为空
暂无日志
`; this.ui.container.appendChild(this.ui.panel); this.setupUIEvents(); } setupUIEvents() { const panel = this.ui.panel; // 切换面板显示 this.ui.container.querySelector('.hypernav-toggle-btn').addEventListener('click', () => { panel.classList.toggle('show'); if (panel.classList.contains('show')) { this.updateUI(); } }); // 关闭面板 panel.querySelector('.hypernav-close-btn').addEventListener('click', () => { panel.classList.remove('show'); }); // 标签切换 panel.querySelectorAll('.hypernav-tab').forEach(tab => { tab.addEventListener('click', () => { panel.querySelectorAll('.hypernav-tab').forEach(t => t.classList.remove('active')); panel.querySelectorAll('.hypernav-tab-content').forEach(c => c.classList.remove('active')); tab.classList.add('active'); const tabId = tab.dataset.tab; panel.querySelector(`#tab-${tabId}`).classList.add('active'); if (tabId === 'cache') { this.updateCacheList(); } }); }); // 控制项事件 const updateConfig = (key, value) => { this.config[key] = value; this.saveConfig(); }; panel.querySelector('#toggle-enabled').addEventListener('change', (e) => { updateConfig('enabled', e.target.checked); if (e.target.checked) { this.start(); } else { this.stop(); } }); panel.querySelector('#select-mode').addEventListener('change', (e) => { updateConfig('mode', e.target.value); }); panel.querySelector('#select-method').addEventListener('change', (e) => { updateConfig('prefetchMethod', e.target.value); this.restartObserver(); }); panel.querySelector('#toggle-learning').addEventListener('change', (e) => { updateConfig('learnBehavior', e.target.checked); }); panel.querySelector('#range-concurrent').addEventListener('input', (e) => { const value = e.target.value; panel.querySelector('#value-concurrent').textContent = value; updateConfig('maxConcurrent', parseInt(value)); }); panel.querySelector('#range-delay').addEventListener('input', (e) => { const value = e.target.value; panel.querySelector('#value-delay').textContent = `${value}ms`; updateConfig('delay', parseInt(value)); }); panel.querySelector('#toggle-external').addEventListener('change', (e) => { updateConfig('ignoreExternal', e.target.checked); }); panel.querySelector('#toggle-debug').addEventListener('change', (e) => { updateConfig('debug', e.target.checked); }); // 按钮事件 panel.querySelector('#btn-refresh').addEventListener('click', () => { this.updateUI(); }); panel.querySelector('#btn-prefetch-now').addEventListener('click', () => { this.prefetchVisibleLinks(); }); panel.querySelector('#btn-clear-cache').addEventListener('click', () => { this.clearCache(); }); panel.querySelector('#btn-clear-logs').addEventListener('click', () => { const container = panel.querySelector('#log-container'); if (container) { container.innerHTML = '
暂无日志
'; } }); // 拖动功能 let isDragging = false; let startX, startY, startLeft, startTop; panel.querySelector('.hypernav-drag-handle').addEventListener('mousedown', (e) => { isDragging = true; startX = e.clientX; startY = e.clientY; const rect = panel.getBoundingClientRect(); startLeft = rect.left; startTop = rect.top; const onMouseMove = (e) => { if (!isDragging) return; const dx = e.clientX - startX; const dy = e.clientY - startY; panel.style.left = (startLeft + dx) + 'px'; panel.style.top = (startTop + dy) + 'px'; }; const onMouseUp = () => { isDragging = false; document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); }; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); // 初始化控制项 panel.querySelector('#toggle-enabled').checked = this.config.enabled; panel.querySelector('#select-mode').value = this.config.mode; panel.querySelector('#select-method').value = this.config.prefetchMethod; panel.querySelector('#toggle-learning').checked = this.config.learnBehavior; panel.querySelector('#range-concurrent').value = this.config.maxConcurrent; panel.querySelector('#value-concurrent').textContent = this.config.maxConcurrent; panel.querySelector('#range-delay').value = this.config.delay; panel.querySelector('#value-delay').textContent = `${this.config.delay}ms`; panel.querySelector('#toggle-external').checked = this.config.ignoreExternal; panel.querySelector('#toggle-debug').checked = this.config.debug; } setupEventListeners() { // 键盘快捷键 document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.shiftKey && e.key === 'H') { e.preventDefault(); this.ui.panel.classList.toggle('show'); if (this.ui.panel.classList.contains('show')) { this.updateUI(); } } if (e.ctrlKey && e.shiftKey && e.key === ' ') { e.preventDefault(); this.toggleEnabled(); } }); // 监听链接点击 document.addEventListener('click', (e) => { let target = e.target; while (target && target.tagName !== 'A') { target = target.parentElement; } if (target && target.href) { this.onLinkClick(target); } }, true); // 监听页面可见性变化 document.addEventListener('visibilitychange', () => { if (!document.hidden && this.config.enabled) { this.restartObserver(); } }); // 监听滚动 let scrollTimer; window.addEventListener('scroll', () => { clearTimeout(scrollTimer); scrollTimer = setTimeout(() => { if (this.config.enabled && this.config.prefetchMethod === 'viewport') { this.prefetchVisibleLinks(); } }, 100); }, { passive: true }); } onLinkClick(link) { const url = link.href; // 检查是否在缓存中 if (this.state.cache.has(url)) { this.state.cacheHits++; this.log(`缓存命中: ${this.getUrlDisplay(url)}`, 'success'); // 记录加速效果 const loadTime = performance.now() - this.state.performance.baseLoadTime; this.state.performance.speedups.push(loadTime); this.state.performance.improvedLoadTime = loadTime; } this.log(`用户点击链接: ${this.getUrlDisplay(url)}`); } toggleEnabled() { this.config.enabled = !this.config.enabled; this.saveConfig(); if (this.config.enabled) { this.start(); this.log('加速器已启用'); } else { this.stop(); this.log('加速器已禁用'); } this.updateUI(); } start() { if (this.state.active || !this.config.enabled) return; this.observeLinks(); this.state.active = true; // 启动UI更新 if (this.ui.updateInterval) { clearInterval(this.ui.updateInterval); } this.ui.updateInterval = setInterval(() => { this.updateUI(); }, 2000); this.log('加速器已启动'); // 初始预取 setTimeout(() => { this.prefetchVisibleLinks(); }, 1000); } stop() { if (this.state.observer) { this.state.observer.disconnect(); this.state.observer = null; } this.state.active = false; if (this.ui.updateInterval) { clearInterval(this.ui.updateInterval); this.ui.updateInterval = null; } this.log('加速器已停止'); } restartObserver() { if (this.state.active) { this.stop(); this.start(); } } observeLinks() { if (!this.config.enabled) return; // 停止现有的观察器 if (this.state.observer) { this.state.observer.disconnect(); } // 获取所有链接 const allLinks = Array.from(document.querySelectorAll('a[href]')); const validLinks = allLinks.filter(link => this.isValidLink(link)); this.state.totalLinks = allLinks.length; this.state.linksObserved = validLinks.length; if (this.config.prefetchMethod === 'viewport') { // 使用IntersectionObserver观察视口内的链接 this.state.observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const link = entry.target; this.schedulePrefetch(link); } }); }, { root: null, rootMargin: '200px', threshold: 0.1 }); validLinks.forEach(link => { this.state.observer.observe(link); }); this.log(`开始观察 ${validLinks.length} 个链接 (视口模式)`); } else if (this.config.prefetchMethod === 'hover') { // 鼠标悬停预取 validLinks.forEach(link => { let hoverTimer; link.addEventListener('mouseenter', () => { clearTimeout(hoverTimer); hoverTimer = setTimeout(() => { this.schedulePrefetch(link); }, this.config.delay); }); link.addEventListener('mouseleave', () => { clearTimeout(hoverTimer); }); }); this.log(`设置 ${validLinks.length} 个链接的悬停预取`); } else if (this.config.prefetchMethod === 'all') { // 预取所有链接 this.log(`开始预取所有 ${validLinks.length} 个链接`); validLinks.forEach(link => { this.schedulePrefetch(link); }); } } isValidLink(link) { if (!link.href) return false; const url = link.href; // 检查忽略模式 for (const pattern of this.ignorePatterns) { if (pattern.test(url)) { return false; } } // 检查是否同源 if (this.config.ignoreExternal) { try { const linkUrl = new URL(url); const currentUrl = new URL(window.location.href); if (linkUrl.origin !== currentUrl.origin) { return false; } } catch (e) { return false; } } // 排除锚点 if (url.includes('#') && (url.split('#')[0] === window.location.href.split('#')[0])) { return false; } return true; } schedulePrefetch(link) { if (!link || !link.href || link._hypernavScheduled) return; link._hypernavScheduled = true; // 添加到队列 this.preloadQueue.push({ link: link, url: link.href, timestamp: Date.now() }); // 处理队列 this.processPreloadQueue(); } async processPreloadQueue() { // 控制并发数 if (this.state.activePrefetches >= this.config.maxConcurrent) { return; } if (this.preloadQueue.length === 0) { return; } const item = this.preloadQueue.shift(); if (!item) return; this.state.activePrefetches++; try { await this.prefetchUrl(item.url, item.link); } catch (error) { // 忽略错误 } finally { this.state.activePrefetches--; // 继续处理队列 setTimeout(() => this.processPreloadQueue(), 100); } } async prefetchUrl(url, link) { // 检查缓存 if (this.state.cache.has(url)) { const cached = this.state.cache.get(url); if (Date.now() - cached.timestamp < this.config.cacheDuration) { this.log(`缓存已存在: ${this.getUrlDisplay(url)}`, 'success'); return true; } } this.log(`开始预取: ${this.getUrlDisplay(url)}`); try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.config.timeout); const response = await fetch(url, { method: 'HEAD', mode: 'no-cors', credentials: 'omit', signal: controller.signal, headers: { 'Purpose': 'prefetch', 'X-Moz': 'prefetch' } }).catch(() => null); clearTimeout(timeoutId); if (response && response.ok) { // 成功预取 this.state.cache.set(url, { timestamp: Date.now(), size: parseInt(response.headers.get('content-length') || '0'), type: response.headers.get('content-type') || 'unknown' }); this.state.linksPrefetched++; this.log(`预取成功: ${this.getUrlDisplay(url)}`, 'success'); // 限制缓存大小 if (this.state.cache.size > 100) { const oldestKey = Array.from(this.state.cache.keys())[0]; this.state.cache.delete(oldestKey); } return true; } } catch (error) { if (this.config.debug) { this.log(`预取失败: ${this.getUrlDisplay(url)} - ${error.message}`, 'error'); } } return false; } prefetchVisibleLinks() { if (!this.config.enabled) return; const viewportLinks = Array.from(document.querySelectorAll('a[href]')).filter(link => { if (!this.isValidLink(link)) return false; const rect = link.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) + 500 && rect.right <= (window.innerWidth || document.documentElement.clientWidth) + 500 ); }); this.log(`找到 ${viewportLinks.length} 个可见链接`); viewportLinks.forEach(link => { this.schedulePrefetch(link); }); } getUrlDisplay(url) { try { const urlObj = new URL(url); return urlObj.pathname + urlObj.search || urlObj.hostname; } catch (e) { return url.substring(0, 50) + (url.length > 50 ? '...' : ''); } } clearCache() { this.state.cache.clear(); this.state.cacheHits = 0; this.state.linksPrefetched = 0; this.updateUI(); this.updateCacheList(); this.log('缓存已清空'); } updateUI() { if (!this.ui.panel || !this.ui.panel.classList.contains('show')) return; const panel = this.ui.panel; // 更新统计 panel.querySelector('#stat-observed').textContent = this.state.linksObserved; panel.querySelector('#stat-prefetched').textContent = this.state.linksPrefetched; panel.querySelector('#stat-cache-hits').textContent = this.state.cacheHits; // 计算加速效果 - 修复计算方式 const speedImprovement = this.calculateSpeedImprovement(); const speedElement = panel.querySelector('#stat-speed'); speedElement.textContent = `${speedImprovement}%`; // 根据加速效果设置颜色 if (speedImprovement >= 50) { speedElement.style.color = '#4caf50'; } else if (speedImprovement >= 20) { speedElement.style.color = '#ff9800'; } else { speedElement.style.color = '#f44336'; } // 更新网络状态 this.updateNetworkStatus(); // 更新页脚 const sessionTime = Math.floor((Date.now() - this.state.sessionStart) / 1000); const minutes = Math.floor(sessionTime / 60); const seconds = sessionTime % 60; panel.querySelector('#footer-stats').textContent = `运行: ${minutes}分${seconds}秒 | 缓存: ${this.state.cache.size} | 并发: ${this.state.activePrefetches}/${this.config.maxConcurrent}`; } calculateSpeedImprovement() { // 更合理的加速效果计算 if (this.state.linksObserved === 0) return 0; // 基于缓存命中率和预取成功率 const cacheHitRate = this.state.cacheHits > 0 ? Math.min(100, (this.state.cacheHits / this.state.linksObserved) * 200) : 0; const prefetchRate = this.state.linksPrefetched > 0 ? Math.min(50, (this.state.linksPrefetched / this.state.linksObserved) * 50) : 0; // 基于页面加载时间的改进 let loadTimeImprovement = 0; if (this.state.performance.speedups.length > 0) { const avgSpeedup = this.state.performance.speedups.reduce((a, b) => a + b, 0) / this.state.performance.speedups.length; loadTimeImprovement = Math.min(30, Math.max(0, 30 - (avgSpeedup / 100))); } // 总加速效果 const totalImprovement = Math.round(cacheHitRate + prefetchRate + loadTimeImprovement); return Math.min(99, totalImprovement); } updateNetworkStatus() { const element = this.ui.panel.querySelector('#network-status'); if (!element) return; const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection; if (connection) { const type = connection.effectiveType || 'unknown'; const downlink = connection.downlink || 0; const rtt = connection.rtt || 0; let status = '良好'; let indicatorClass = 'hypernav-network-good'; if (type.includes('2g') || rtt > 300) { status = '较慢'; indicatorClass = 'hypernav-network-medium'; } if (type.includes('slow-2g') || rtt > 1000) { status = '极慢'; indicatorClass = 'hypernav-network-poor'; } element.innerHTML = `
网络: ${type.toUpperCase()} | 延迟: ${rtt}ms `; } else { element.innerHTML = `
网络状态: 未知 `; } } updateCacheList() { const container = this.ui.panel.querySelector('#cache-list'); const countElement = this.ui.panel.querySelector('#cache-count'); if (!container) return; if (this.state.cache.size === 0) { container.innerHTML = '
缓存为空
'; if (countElement) countElement.textContent = '0'; return; } if (countElement) countElement.textContent = this.state.cache.size; let html = ''; let count = 0; const now = Date.now(); // 清理过期缓存 for (const [url, data] of this.state.cache.entries()) { if (now - data.timestamp > this.config.cacheDuration) { this.state.cache.delete(url); } } for (const [url, data] of this.state.cache.entries()) { if (count++ >= 20) break; const age = now - data.timestamp; const ageMinutes = Math.floor(age / 60000); const ageText = ageMinutes < 1 ? '刚刚' : `${ageMinutes}分钟前`; const displayUrl = this.getUrlDisplay(url); html += `
${displayUrl}
${ageText}
`; } container.innerHTML = html || '
缓存为空
'; } log(message, type = 'info') { // 只在调试模式记录info日志 if (!this.config.debug && type === 'info') return; if (this.config.debug) { console.log(`[HyperNav] ${message}`); } const logContainer = this.ui.panel?.querySelector('#log-container'); if (!logContainer) return; const entry = document.createElement('div'); entry.className = `hypernav-log-entry ${type}`; entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; logContainer.appendChild(entry); // 限制日志数量 const entries = logContainer.querySelectorAll('.hypernav-log-entry'); if (entries.length > 50) { entries[0].remove(); } // 自动滚动到底部 logContainer.scrollTop = logContainer.scrollHeight; } getStats() { return { enabled: this.config.enabled, mode: this.config.mode, linksObserved: this.state.linksObserved, linksPrefetched: this.state.linksPrefetched, cacheHits: this.state.cacheHits, cacheSize: this.state.cache.size, speedImprovement: this.calculateSpeedImprovement() + '%', sessionTime: Math.floor((Date.now() - this.state.sessionStart) / 1000) + '秒' }; } } // 初始化 window.hypernav = new HyperNav(); // 在控制台暴露API console.log('🚀 网页加速器 v3.0.0 已加载!'); console.log('使用说明:'); console.log('1. 点击右下角火箭图标打开控制面板'); console.log('2. 使用 Ctrl+Shift+H 快速开关面板'); console.log('3. 使用 Ctrl+Shift+空格 切换加速开关'); console.log('4. 可用命令: hypernav.getStats()'); })();