您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
配置冻结 + 精确正则匹配的安全强化版本(搜索引擎翻页优化)
// ==UserScript== // @name Automagic网址自动替换 - 终极安全强化版 v6.8 // @namespace http://tampermonkey.net/ // @version 6.8 // @description 配置冻结 + 精确正则匹配的安全强化版本(搜索引擎翻页优化) // @author Jeff_CF // @icon https://46.231.200.187/images/AutomagicAdaptiveIcon_25.png // @match *://46.231.200.187/* // @match *://automagic4android.com/* // @match *://*/* // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_addStyle // @grant GM_xmlhttpRequest // @run-at document-start // ==/UserScript== (function() { 'use strict'; // 深度冻结配置对象 const CONFIG = deepFreeze({ OLD_DOMAIN: 'automagic4android.com', NEW_IP: '46.231.200.187', URL_ATTRIBUTES: Object.freeze([ 'href', 'src', 'action', 'data-src', 'data-url', 'data-href', 'srcset', 'cite', 'formaction' ]), DEBOUNCE_DELAY: 50, MAX_BATCH_SIZE: 100, MAX_DEPTH: 2, SECURE_PROTOCOLS: Object.freeze(['http:', 'https:', 'ftp:']), EXCLUDED_DOMAINS: Object.freeze(['google.com', 'cloudflare.com']), PERFORMANCE_LOGGING: true, PROCESS_EXTERNAL_CSS: false, STATIC_PAGE_PATTERNS: Object.freeze([ /^https?:\/\/(www\.)?google\.(com|co\.[a-z]{2})\/search\?/i, /^https?:\/\/(www\.)?bing\.com\/search\?/i, /^https?:\/\/(www\.)?yahoo\.com\/search\?/i, /^https?:\/\/(www\.)?duckduckgo\.com\/\?/i, /^https?:\/\/(www\.)?baidu\.com\/(s|wd=\w)/i ]), URL_LIKE_REGEX: /^(https?|ftp):\/\/|^\/\/|^\/[^\/\s]|^\.\.?\/|^mailto:|^tel:|^#/i, FRAMEWORK_CONTAINERS: Object.freeze([ '#root', '#app', '.react-root', '.vue-app', '[data-reactroot]' ]), EXTRA_SCAN_DELAY: 300, SEARCH_ENGINE_CONFIG: Object.freeze({ 'www.baidu.com': { container: '#content_left', itemSelector: '.result', paginationParam: 'pn', nextButton: '#page > a.n' }, 'www.google.com': { container: '#rso', itemSelector: '.g', paginationParam: 'start' }, 'www.bing.com': { container: '#b_results', itemSelector: '.b_algo', paginationParam: 'first' } }) }); // 性能监控器 const performanceMetrics = { processedElements: 0, processedMutations: 0, processedCSS: 0, lastReportTime: Date.now(), mutationObserverEnabled: true, extraScans: 0, mixedContentWarnings: 0, navigationEvents: 0, searchResultsProcessed: 0 }; // 错误跟踪器 const errorTracker = { elementErrors: 0, cssErrors: 0, mutationErrors: 0, skippedDataAttributes: 0, externalCSSErrors: 0, regexErrors: 0, navigationErrors: 0 }; // 预编译排除域名正则 const EXCLUDED_REGEX = (function() { const domains = CONFIG.EXCLUDED_DOMAINS.map(domain => { return `(^|\\.)${domain.replace(/\./g, '\\.')}$`; }).join('|'); return new RegExp(domains); })(); // 深度冻结函数 function deepFreeze(object) { if (!object || typeof object !== 'object') return object; Object.freeze(object); Object.getOwnPropertyNames(object).forEach(prop => { if (object[prop] !== null && (typeof object[prop] === 'object' || typeof object[prop] === 'function') && !Object.isFrozen(object[prop])) { deepFreeze(object[prop]); } }); return object; } // 预编译正则表达式 const DOMAIN_REGEX = (function() { const escapedDomain = CONFIG.OLD_DOMAIN.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); return new RegExp( `\\b${escapedDomain}\\b`, 'gi' ); })(); // 获取基准URL(处理<base>标签) function getBaseUrl() { const baseElement = document.querySelector('base[href]'); return baseElement ? baseElement.href : window.location.href; } // 安全URI解码 function safeDecodeURI(uri) { try { return decodeURIComponent(uri); } catch { return uri; } } // 检查是否在白名单中 function isExcludedDomain(url) { try { const { hostname } = new URL(url); return EXCLUDED_REGEX.test(hostname); } catch { return false; } } // 检查是否是静态页面(如搜索引擎) function isStaticPage() { return CONFIG.STATIC_PAGE_PATTERNS.some(pattern => pattern.test(window.location.href) ); } // 检查值是否像URL function isUrlLike(value) { return CONFIG.URL_LIKE_REGEX.test(value) || value.includes(CONFIG.OLD_DOMAIN); } // 精确URL替换 function replaceUrl(url, base = getBaseUrl()) { // 跳过白名单域名 if (isExcludedDomain(url)) return url; // 处理相对路径 - 使用页面基准URL if (url.startsWith('/') || url.startsWith('./') || url.startsWith('../')) { try { const absoluteUrl = new URL(url, base).href; return absoluteUrl.replace(DOMAIN_REGEX, CONFIG.NEW_IP); } catch { return url; } } // 处理协议相对URL (//example.com) if (url.startsWith('//')) { const protocol = window.location.protocol === 'https:' ? 'https:' : 'http:'; const baseUrl = `${protocol}${url}`; return baseUrl.replace(DOMAIN_REGEX, CONFIG.NEW_IP); } // 处理安全协议 if (!CONFIG.SECURE_PROTOCOLS.some(p => url.startsWith(p))) { return url; } // 检查混合内容 if (window.location.protocol === 'https:' && url.startsWith('http:')) { performanceMetrics.mixedContentWarnings++; console.warn(`Automagic: 混合内容警告 - HTTP资源在HTTPS页面: ${url}`); } const decodedUrl = safeDecodeURI(url); try { return decodedUrl.replace(DOMAIN_REGEX, (match) => { // 保持原始协议 const protocol = match.startsWith('https') ? 'https://' : match.startsWith('http') ? 'http://' : match.startsWith('ftp') ? 'ftp://' : '//'; return protocol + CONFIG.NEW_IP; }); } catch (e) { errorTracker.regexErrors++; console.warn('Automagic: URL替换错误', e); return url; } } // 安全处理srcset属性 function processSrcset(srcset) { return srcset.split(',') .map(part => { const [url, ...descriptors] = part.trim().split(/\s+/); const newUrl = replaceUrl(url); return [newUrl, ...descriptors].join(' '); }) .join(', '); } // 处理单个元素 function processElement(element) { try { // 跳过跨域iframe if (element.tagName === 'IFRAME' && element.contentDocument === null && element.src && element.src !== 'about:blank') { console.warn('Automagic: 跳过跨域iframe', element.src); return; } for (const attr of CONFIG.URL_ATTRIBUTES) { const value = element.getAttribute(attr); if (!value) continue; // 跳过非URL类data属性 if (attr.startsWith('data-') && !isUrlLike(value)) { errorTracker.skippedDataAttributes++; continue; } let newValue; if (attr === 'srcset') { newValue = processSrcset(value); } else { newValue = replaceUrl(value); } if (newValue !== value) { element.setAttribute(attr, newValue); performanceMetrics.processedElements++; } } } catch (e) { errorTracker.elementErrors++; console.warn('Automagic元素处理错误:', e.message, '\n元素:', element.outerHTML.slice(0, 200)); } } // 批量处理元素 function processElements(elements) { const startTime = performance.now(); const batch = Math.min(elements.length, CONFIG.MAX_BATCH_SIZE); for (let i = 0; i < batch; i++) { processElement(elements[i]); } // 记录性能 if (CONFIG.PERFORMANCE_LOGGING) { const duration = performance.now() - startTime; console.debug(`Automagic: 处理 ${batch} 个元素, 耗时 ${duration.toFixed(2)}ms`); } // 分批处理剩余元素 if (elements.length > CONFIG.MAX_BATCH_SIZE) { setTimeout(() => { processElements(Array.from(elements).slice(CONFIG.MAX_BATCH_SIZE)); }, CONFIG.DEBOUNCE_DELAY); } } // 扫描框架容器 function scanFrameworkContainers() { const containers = CONFIG.FRAMEWORK_CONTAINERS .map(selector => document.querySelector(selector)) .filter(el => el !== null); if (containers.length === 0) return; containers.forEach(container => { const selector = CONFIG.URL_ATTRIBUTES .map(attr => `[${attr}]`) .join(','); if (!selector) return; try { const elements = container.querySelectorAll(selector); if (elements.length > 0) { console.debug(`Automagic: 在框架容器中发现${elements.length}个元素`); processElements(elements); } } catch (e) { console.warn('Automagic框架容器扫描错误:', e); } }); } // 获取当前搜索引擎配置 function getSearchEngineConfig() { const hostname = window.location.hostname; for (const domain in CONFIG.SEARCH_ENGINE_CONFIG) { if (hostname.includes(domain)) { return CONFIG.SEARCH_ENGINE_CONFIG[domain]; } } return null; } // 处理搜索引擎结果 function processSearchResults() { const config = getSearchEngineConfig(); if (!config) return; const container = document.querySelector(config.container); if (!container) return; const items = container.querySelectorAll(config.itemSelector); items.forEach(item => { // 跳过已处理的项 if (item.getAttribute('data-automagic-processed') === 'true') return; CONFIG.URL_ATTRIBUTES.forEach(attr => { const elements = item.querySelectorAll(`[${attr}]`); elements.forEach(el => { processElement(el); }); }); item.setAttribute('data-automagic-processed', 'true'); performanceMetrics.searchResultsProcessed++; }); } // 设置翻页监听器 function setupPaginationListeners() { // 代理History API const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function(...args) { originalPushState.apply(this, args); handlePageNavigation(); }; history.replaceState = function(...args) { originalReplaceState.apply(this, args); handlePageNavigation(); }; // 监听popstate事件 window.addEventListener('popstate', handlePageNavigation); // 监听百度"下一页"按钮 const config = getSearchEngineConfig(); if (config && config.nextButton) { const nextButton = document.querySelector(config.nextButton); if (nextButton) { nextButton.addEventListener('click', () => { sessionStorage.setItem('forceRescan', 'true'); handlePageNavigation(); }); } } } // 处理页面导航 let navigationTimer = null; function handlePageNavigation() { clearTimeout(navigationTimer); navigationTimer = setTimeout(() => { try { performanceMetrics.navigationEvents++; if (isStaticPage()) { console.log('Automagic: 检测到翻页操作,重新处理搜索结果'); processSearchResults(); } } catch (e) { errorTracker.navigationErrors++; console.error('Automagic: 翻页处理错误', e); } }, 500); // 500ms延迟确保DOM更新完成 } // 初始页面处理 function processInitialPage() { const selector = CONFIG.URL_ATTRIBUTES .map(attr => `[${attr}]`) .join(','); if (!selector) return; try { const elements = document.querySelectorAll(selector); processElements(elements); // 处理CSS样式 processAllCSS(); // 扫描框架容器 scanFrameworkContainers(); // 处理搜索引擎结果 if (isStaticPage()) { processSearchResults(); setupPaginationListeners(); } // 额外扫描(针对异步渲染) if (!isStaticPage()) { setTimeout(() => { console.debug('Automagic: 执行额外扫描'); processInitialPage(); performanceMetrics.extraScans++; }, CONFIG.EXTRA_SCAN_DELAY); } } catch (e) { console.warn('Automagic初始处理错误:', e.message); } } // 处理所有CSS样式 function processAllCSS() { // 处理<style>元素 document.querySelectorAll('style').forEach(styleEl => { processStyleElement(styleEl); }); // 处理外部CSS(可选) if (CONFIG.PROCESS_EXTERNAL_CSS) { document.querySelectorAll('link[rel="stylesheet"]').forEach(linkEl => { processExternalCSS(linkEl); }); } } // 处理<style>元素 function processStyleElement(styleEl) { try { const newCss = styleEl.textContent.replace( /url\(['"]?(.*?)['"]?\)/gi, (match, url) => { const newUrl = replaceUrl(url); if (newUrl !== url) { performanceMetrics.processedCSS++; return `url("${newUrl}")`; } return match; } ); if (newCss !== styleEl.textContent) { styleEl.textContent = newCss; } } catch (e) { errorTracker.cssErrors++; console.warn('Automagic CSS处理错误:', e.message); } } // 处理外部CSS function processExternalCSS(linkEl) { try { const href = linkEl.getAttribute('href'); if (!href) return; // 检查同源策略 if (href.startsWith('http') && !isSameOrigin(href)) { console.warn(`Automagic: 跳过跨域CSS ${href}`); errorTracker.externalCSSErrors++; return; } const newHref = replaceUrl(href); if (newHref !== href) { linkEl.setAttribute('href', newHref); } } catch (e) { errorTracker.cssErrors++; console.warn('Automagic外部CSS处理错误:', e.message); } } // 检查是否同源 function isSameOrigin(url) { try { const target = new URL(url); const current = new URL(window.location.href); return target.origin === current.origin; } catch { return false; } } // 处理DOM变化 function handleMutations(mutations) { try { performanceMetrics.processedMutations++; const elementsToProcess = new Set(); const selector = CONFIG.URL_ATTRIBUTES.map(attr => `[${attr}]`).join(','); for (const mutation of mutations) { // 处理新增节点 if (mutation.addedNodes) { for (const node of mutation.addedNodes) { try { if (node.nodeType === Node.ELEMENT_NODE) { // 检查节点本身 if (selector && node.matches(selector)) { elementsToProcess.add(node); } // 批量查询子节点 if (node.querySelectorAll) { const children = node.querySelectorAll(selector); children.forEach(child => elementsToProcess.add(child)); } // 处理动态样式 if (node.tagName === 'STYLE') { setTimeout(() => processStyleElement(node), 0); } // 处理外部CSS if (node.tagName === 'LINK' && node.getAttribute('rel') === 'stylesheet' && CONFIG.PROCESS_EXTERNAL_CSS) { setTimeout(() => processExternalCSS(node), 0); } } } catch (e) { errorTracker.mutationErrors++; console.debug('Automagic: 跳过无法处理的节点', e); } } } // 处理属性变化 if (mutation.type === 'attributes' && CONFIG.URL_ATTRIBUTES.includes(mutation.attributeName)) { elementsToProcess.add(mutation.target); } } // 处理收集到的元素 if (elementsToProcess.size > 0) { processElements(Array.from(elementsToProcess)); } // 定期报告性能 if (CONFIG.PERFORMANCE_LOGGING && Date.now() - performanceMetrics.lastReportTime > 10000) { console.log(`Automagic性能报告: 处理元素: ${performanceMetrics.processedElements} 处理变动: ${performanceMetrics.processedMutations} CSS处理: ${performanceMetrics.processedCSS} 额外扫描: ${performanceMetrics.extraScans} 翻页事件: ${performanceMetrics.navigationEvents} 搜索结果处理: ${performanceMetrics.searchResultsProcessed} 混合内容警告: ${performanceMetrics.mixedContentWarnings} 错误统计: 元素: ${errorTracker.elementErrors} CSS: ${errorTracker.cssErrors} 变动: ${errorTracker.mutationErrors} 导航: ${errorTracker.navigationErrors} 外部CSS: ${errorTracker.externalCSSErrors} 正则: ${errorTracker.regexErrors} 跳过的非URL属性: ${errorTracker.skippedDataAttributes}`); performanceMetrics.lastReportTime = Date.now(); } } catch (e) { console.error('Automagic变动处理错误:', e); } } // 防抖的MutationObserver let mutationTimer = null; function mutationCallback(mutations) { if (mutationTimer) clearTimeout(mutationTimer); mutationTimer = setTimeout(() => { handleMutations(mutations); mutationTimer = null; }, CONFIG.DEBOUNCE_DELAY); } // 初始化MutationObserver function initObserver() { // 静态页面禁用MutationObserver if (isStaticPage()) { console.log('Automagic: 静态页面检测,禁用MutationObserver'); performanceMetrics.mutationObserverEnabled = false; return null; } const observer = new MutationObserver(mutationCallback); observer.observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: CONFIG.URL_ATTRIBUTES }); return observer; } // 注册用户菜单 function registerUserCommands() { try { // 性能报告 GM_registerMenuCommand("🚀 显示性能报告", () => { alert(`Automagic性能报告: 处理元素: ${performanceMetrics.processedElements} 处理变动: ${performanceMetrics.processedMutations} CSS处理: ${performanceMetrics.processedCSS} 额外扫描: ${performanceMetrics.extraScans} 翻页事件: ${performanceMetrics.navigationEvents} 搜索结果处理: ${performanceMetrics.searchResultsProcessed} 混合内容警告: ${performanceMetrics.mixedContentWarnings} 错误统计: 元素: ${errorTracker.elementErrors} CSS: ${errorTracker.cssErrors} 变动: ${errorTracker.mutationErrors} 导航: ${errorTracker.navigationErrors} 外部CSS: ${errorTracker.externalCSSErrors} 正则: ${errorTracker.regexErrors} 跳过的非URL属性: ${errorTracker.skippedDataAttributes} MutationObserver状态: ${performanceMetrics.mutationObserverEnabled ? '启用' : '禁用'}`); }); // 临时禁用脚本 GM_registerMenuCommand("⏸️ 临时禁用脚本", () => { GM_setValue('scriptEnabled', false); alert("脚本已禁用,刷新页面后生效"); }); // 启用脚本 GM_registerMenuCommand("▶️ 启用脚本", () => { GM_setValue('scriptEnabled', true); alert("脚本已启用,刷新页面后生效"); }); // 切换性能日志 GM_registerMenuCommand("📊 切换性能日志", () => { const current = GM_getValue('performanceLogging', CONFIG.PERFORMANCE_LOGGING); GM_setValue('performanceLogging', !current); alert(`性能日志已${!current ? '启用' : '禁用'}`); }); // 调整批量大小 GM_registerMenuCommand("⚙️ 调整批量大小", () => { const newSize = prompt("请输入新的批量处理大小 (10-500):", CONFIG.MAX_BATCH_SIZE); if (newSize && !isNaN(newSize) && newSize >= 10 && newSize <= 500) { GM_setValue('batchSize', parseInt(newSize)); alert(`批量大小已设置为${newSize}`); } }); // 切换外部CSS处理 GM_registerMenuCommand("🎨 切换外部CSS处理", () => { const current = GM_getValue('processExternalCSS', CONFIG.PROCESS_EXTERNAL_CSS); const newValue = !current; GM_setValue('processExternalCSS', newValue); if (newValue) { alert(`外部CSS处理已启用(注意跨域风险)`); CONFIG.PROCESS_EXTERNAL_CSS = true; processAllCSS(); } else { alert(`外部CSS处理已禁用`); CONFIG.PROCESS_EXTERNAL_CSS = false; } }); } catch (e) { console.debug('Automagic: 此环境不支持用户命令'); } } // 增强SPA支持 function initSPASupport() { // 监听history变化 const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function() { originalPushState.apply(this, arguments); setTimeout(processInitialPage, 100); }; history.replaceState = function() { originalReplaceState.apply(this, arguments); setTimeout(processInitialPage, 100); }; // 监听路由变化 window.addEventListener('popstate', () => { setTimeout(processInitialPage, 100); }); window.addEventListener('hashchange', () => { setTimeout(processInitialPage, 100); }); } // 主初始化函数 function init() { // 检查是否被禁用 if (GM_getValue('scriptEnabled', true) === false) return; // 应用用户配置 if (GM_getValue('performanceLogging') !== undefined) { CONFIG.PERFORMANCE_LOGGING = GM_getValue('performanceLogging'); } if (GM_getValue('batchSize')) { CONFIG.MAX_BATCH_SIZE = GM_getValue('batchSize'); } if (GM_getValue('processExternalCSS') !== undefined) { CONFIG.PROCESS_EXTERNAL_CSS = GM_getValue('processExternalCSS'); } // 初始页面处理 processInitialPage(); // 初始化观察器 initObserver(); // 初始化SPA支持 initSPASupport(); // 注册用户命令 setTimeout(registerUserCommands, 2000); // 添加性能监控面板 addPerformancePanel(); } // 添加性能监控面板 function addPerformancePanel() { if (!CONFIG.PERFORMANCE_LOGGING) return; GM_addStyle(` #automagic-panel { position: fixed; bottom: 10px; right: 10px; background: rgba(0,0,0,0.85); color: white; padding: 15px; border-radius: 10px; font-family: Arial, sans-serif; font-size: 13px; z-index: 9999; max-width: 320px; backdrop-filter: blur(5px); box-shadow: 0 4px 12px rgba(0,0,0,0.2); border: 1px solid #4CAF50; cursor: move; user-select: none; } #automagic-panel h3 { margin: 0 0 10px 0; font-size: 15px; color: #4CAF50; display: flex; align-items: center; gap: 8px; } #automagic-panel .stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 10px; } #automagic-panel .stat { display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.1); } #automagic-panel .stat-value { font-weight: bold; color: #4CAF50; } #automagic-panel .stat.warning .stat-value { color: #ffd166; } #automagic-panel .stat.error .stat-value { color: #ff6b6b; } #automagic-panel .controls { display: flex; gap: 8px; margin-top: 10px; } #automagic-panel button { flex: 1; background: #4CAF50; border: none; color: white; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 12px; transition: all 0.2s; } #automagic-panel button:hover { background: #3d8b40; transform: translateY(-2px); } #automagic-panel button.warning { background: #ff9800; } #automagic-panel button.warning:hover { background: #e68a00; } #automagic-panel button.danger { background: #f44336; } #automagic-panel button.danger:hover { background: #d32f2f; } `); const panel = document.createElement('div'); panel.id = 'automagic-panel'; panel.innerHTML = ` <h3><i class="fas fa-chart-line"></i> Automagic 性能监控</h3> <div class="stats"> <div class="stat"><span>处理元素:</span> <span id="automagic-elements" class="stat-value">0</span></div> <div class="stat"><span>搜索结果:</span> <span id="automagic-search-results" class="stat-value">0</span></div> <div class="stat"><span>翻页事件:</span> <span id="automagic-navigations" class="stat-value">0</span></div> <div class="stat warning"><span>混合内容:</span> <span id="automagic-mixed" class="stat-value">0</span></div> <div class="stat"><span>额外扫描:</span> <span id="automagic-extrascans" class="stat-value">0</span></div> <div class="stat error"><span>元素错误:</span> <span id="automagic-element-errors" class="stat-value">0</span></div> <div class="stat error"><span>导航错误:</span> <span id="automagic-navigation-errors" class="stat-value">0</span></div> </div> <div class="controls"> <button id="automagic-refresh"><i class="fas fa-sync"></i> 刷新</button> <button id="automagic-hide"><i class="fas fa-eye-slash"></i> 隐藏</button> <button class="danger" id="automagic-debug">调试模式</button> </div> `; document.body.appendChild(panel); // 使面板可拖动 let isDragging = false; let offsetX, offsetY; panel.querySelector('h3').addEventListener('mousedown', function(e) { isDragging = true; offsetX = e.clientX - panel.getBoundingClientRect().left; offsetY = e.clientY - panel.getBoundingClientRect().top; panel.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', function(e) { if (isDragging) { panel.style.left = (e.clientX - offsetX) + 'px'; panel.style.top = (e.clientY - offsetY) + 'px'; } }); document.addEventListener('mouseup', function() { isDragging = false; panel.style.cursor = 'move'; }); // 刷新按钮 panel.querySelector('#automagic-refresh').addEventListener('click', () => { processInitialPage(); console.log('Automagic: 手动刷新页面处理'); }); // 隐藏按钮 panel.querySelector('#automagic-hide').addEventListener('click', function() { panel.style.display = 'none'; // 添加重新显示按钮 const showBtn = document.createElement('button'); showBtn.textContent = '显示面板'; showBtn.style.position = 'fixed'; showBtn.style.bottom = '10px'; showBtn.style.right = '10px'; showBtn.style.zIndex = '9999'; showBtn.style.background = '#4CAF50'; showBtn.style.color = 'white'; showBtn.style.padding = '6px 12px'; showBtn.style.borderRadius = '4px'; showBtn.style.border = 'none'; showBtn.style.cursor = 'pointer'; showBtn.addEventListener('click', function() { panel.style.display = 'block'; showBtn.remove(); }); document.body.appendChild(showBtn); }); // 调试模式按钮 let debugMode = false; panel.querySelector('#automagic-debug').addEventListener('click', function() { debugMode = !debugMode; if (debugMode) { this.innerHTML = '<i class="fas fa-bug"></i> 调试中...'; this.style.background = '#f44336'; console.debug('Automagic: 调试模式已启用'); } else { this.innerHTML = '<i class="fas fa-bug"></i> 调试模式'; this.style.background = ''; console.debug('Automagic: 调试模式已禁用'); } }); // 定期更新面板 setInterval(() => { document.getElementById('automagic-elements').textContent = performanceMetrics.processedElements; document.getElementById('automagic-search-results').textContent = performanceMetrics.searchResultsProcessed; document.getElementById('automagic-navigations').textContent = performanceMetrics.navigationEvents; document.getElementById('automagic-mixed').textContent = performanceMetrics.mixedContentWarnings; document.getElementById('automagic-extrascans').textContent = performanceMetrics.extraScans; document.getElementById('automagic-element-errors').textContent = errorTracker.elementErrors; document.getElementById('automagic-navigation-errors').textContent = errorTracker.navigationErrors; }, 1000); } // 尽早执行 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { setTimeout(init, 0); } })();