// ==UserScript== // @name 网页加速器专业版 // @namespace https://docs.scriptcat.org/ // @version 2.0.0 // @description 智能预加载和缓存网页,显著提升浏览速度 // @author HyperNav // @match https://*/* // @match http://*/* // @grant none // @noframes // @icon https://img.icons8.com/color/96/000000/rocket.png // ==/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; color: #667eea; 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; } `; document.head.appendChild(style); // 主类 class HyperNav { constructor() { this.config = { enabled: true, mode: 'balanced', prefetchMethod: 'viewport', maxConcurrent: 3, delay: 150, threshold: 0.3, timeout: 5000, cacheDuration: 300000, learnBehavior: true, showUI: true, debug: false }; this.state = { initialized: false, active: false, linksObserved: 0, linksPrefetched: 0, cacheHits: 0, cache: new Map(), observer: null, uiVisible: false }; 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 ]; this.init(); } init() { this.loadConfig(); this.createUI(); this.setupEventListeners(); if (this.config.enabled) { this.start(); } this.state.initialized = true; this.log('HyperNav 初始化完成'); } loadConfig() { try { const saved = localStorage.getItem('hypernav-config'); if (saved) { Object.assign(this.config, JSON.parse(saved)); } } catch (e) { console.warn('加载配置失败:', e); } } saveConfig() { try { localStorage.setItem('hypernav-config', JSON.stringify(this.config)); } catch (e) { console.warn('保存配置失败:', e); } } 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 = '网页加速器控制面板'; this.ui.container.appendChild(toggleBtn); // 创建控制面板 this.ui.panel = document.createElement('div'); this.ui.panel.className = 'hypernav-panel'; this.ui.panel.innerHTML = `

🚀 网页加速器

v2.0.0
控制台
缓存
日志
0
观察链接
0
已预取
0
缓存命中
0%
加速效果
网络状态: 检测中...
启用加速
工作模式
智能学习
并发数量
3
预取延迟
150ms
缓存为空
暂无日志
`; 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'); }); // 关闭面板 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'); }); }); // 控制项事件 panel.querySelector('#toggle-enabled').addEventListener('change', (e) => { this.config.enabled = e.target.checked; this.saveConfig(); if (this.config.enabled) { this.start(); } else { this.stop(); } }); panel.querySelector('#select-mode').addEventListener('change', (e) => { this.config.mode = e.target.value; this.saveConfig(); }); panel.querySelector('#toggle-learning').addEventListener('change', (e) => { this.config.learnBehavior = e.target.checked; this.saveConfig(); }); panel.querySelector('#range-concurrent').addEventListener('input', (e) => { const value = e.target.value; panel.querySelector('#value-concurrent').textContent = value; this.config.maxConcurrent = parseInt(value); this.saveConfig(); }); panel.querySelector('#range-delay').addEventListener('input', (e) => { const value = e.target.value; panel.querySelector('#value-delay').textContent = `${value}ms`; this.config.delay = parseInt(value); this.saveConfig(); }); // 按钮事件 panel.querySelector('#btn-refresh').addEventListener('click', () => { this.updateUI(); }); panel.querySelector('#btn-clear-cache').addEventListener('click', () => { if (confirm('确定要清空所有缓存吗?')) { this.state.cache.clear(); this.state.cacheHits = 0; this.updateUI(); this.log('缓存已清空'); } }); // 拖动功能 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; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); }); 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); }; // 初始化控制项 panel.querySelector('#toggle-enabled').checked = this.config.enabled; panel.querySelector('#select-mode').value = this.config.mode; 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`; } setupEventListeners() { // 键盘快捷键 document.addEventListener('keydown', (e) => { if (e.ctrlKey && e.shiftKey && e.key === 'H') { e.preventDefault(); this.ui.panel.classList.toggle('show'); } 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.log('链接点击', target.href); } }, true); // 监听页面可见性变化 document.addEventListener('visibilitychange', () => { if (!document.hidden && this.config.enabled) { this.start(); } }); } toggleEnabled() { this.config.enabled = !this.config.enabled; this.saveConfig(); if (this.config.enabled) { this.start(); } else { this.stop(); } this.updateUI(); this.log(`加速器已${this.config.enabled ? '启用' : '禁用'}`); } start() { if (this.state.active) return; this.observeLinks(); this.state.active = true; // 启动UI更新 if (this.ui.updateInterval) { clearInterval(this.ui.updateInterval); } this.ui.updateInterval = setInterval(() => { this.updateUI(); }, 1000); this.log('加速器已启动'); } stop() { if (this.state.observer) { this.state.observer.disconnect(); } this.state.active = false; if (this.ui.updateInterval) { clearInterval(this.ui.updateInterval); this.ui.updateInterval = null; } this.log('加速器已停止'); } observeLinks() { if (!this.config.enabled) return; if (this.state.observer) { this.state.observer.disconnect(); } this.state.observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const link = entry.target; this.handleLink(link); } }); }, { root: null, rootMargin: '100px', threshold: 0.1 }); const links = Array.from(document.querySelectorAll('a[href]')).filter(link => { return !link.href.includes('#') && !link.href.includes('javascript:') && !this.shouldIgnore(link.href); }); links.forEach(link => { this.state.observer.observe(link); this.state.linksObserved++; // 鼠标悬停预取 link.addEventListener('mouseenter', () => { if (this.config.prefetchMethod === 'hover') { this.prefetchLink(link); } }, { once: true }); }); this.log(`开始观察 ${links.length} 个链接`); } shouldIgnore(url) { try { for (const pattern of this.ignorePatterns) { if (pattern.test(url)) { return true; } } return false; } catch (e) { return true; } } async prefetchLink(link) { if (!link || !link.href || !this.config.enabled) return; const url = link.href; // 检查缓存 if (this.state.cache.has(url)) { const cached = this.state.cache.get(url); if (Date.now() - cached.timestamp < this.config.cacheDuration) { this.state.cacheHits++; return true; } } // 并发控制 if (this.state.activePrefetches >= this.config.maxConcurrent) { return false; } this.state.activePrefetches = (this.state.activePrefetches || 0) + 1; try { // 延迟预取 await new Promise(resolve => setTimeout(resolve, this.config.delay)); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.config.timeout); const response = await fetch(url, { method: 'HEAD', mode: 'cors', credentials: 'same-origin', signal: controller.signal, headers: { 'X-Purpose': 'prefetch' } }); clearTimeout(timeoutId); if (response.ok) { const contentType = response.headers.get('content-type') || ''; if (contentType.includes('text/html')) { this.state.cache.set(url, { timestamp: Date.now(), size: parseInt(response.headers.get('content-length') || '0') }); this.state.linksPrefetched++; this.log(`预取成功: ${new URL(url).pathname}`); return true; } } } catch (error) { if (this.config.debug) { console.log('预取失败:', url, error); } } finally { this.state.activePrefetches--; } return false; } handleLink(link) { if (link._hypernavProcessed) return; link._hypernavProcessed = true; this.prefetchLink(link); // 学习用户行为 link.addEventListener('click', () => { this.log(`用户点击: ${new URL(link.href).pathname}`); }, { once: true }); } 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(); panel.querySelector('#stat-speed').textContent = `${speedImprovement}%`; panel.querySelector('#stat-speed').style.color = speedImprovement > 50 ? '#4caf50' : speedImprovement > 20 ? '#ff9800' : '#f44336'; // 更新网络状态 this.updateNetworkStatus(); // 更新缓存列表 this.updateCacheList(); // 更新页脚 panel.querySelector('#footer-stats').textContent = `缓存: ${this.state.cache.size} | 最后更新: ${new Date().toLocaleTimeString()}`; } calculateSpeedImprovement() { if (this.state.linksObserved === 0) return 0; const hitRate = (this.state.cacheHits / this.state.linksObserved) * 100; return Math.min(99, Math.round(hitRate * 1.5)); } 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 | 速度: ${downlink}Mbps `; } else { element.innerHTML = `
网络状态: 未知 `; } } updateCacheList() { const container = this.ui.panel.querySelector('#cache-list'); if (!container) return; if (this.state.cache.size === 0) { container.innerHTML = '
缓存为空
'; return; } let html = ''; let count = 0; for (const [url, data] of this.state.cache.entries()) { if (count++ >= 20) break; // 只显示前20条 const age = Date.now() - data.timestamp; const ageText = age < 60000 ? '刚刚' : age < 3600000 ? `${Math.floor(age / 60000)}分钟前` : `${Math.floor(age / 3600000)}小时前`; const urlObj = new URL(url); const displayUrl = urlObj.pathname + urlObj.search; html += `
${displayUrl}
${ageText}
`; } container.innerHTML = html; } log(message, type = 'info') { if (!this.config.debug && type === 'info') return; 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() + '%' }; } } // 初始化 window.hypernav = new HyperNav(); // 在控制台暴露API console.log('🚀 网页加速器已加载!使用 Ctrl+Shift+H 打开控制面板'); console.log('可用命令: hypernav.getStats()'); })();