// ==UserScript== // @name 点击网址链接变色 Persistent Red Link // @namespace http://tampermonkey.net/ // @match *://*/* // @grant 市政502 // @version 2025.6.29 // @description zh-cn // @license GNU General Public License v3.0 // @downloadURL none // ==/UserScript== (function () { 'use strict'; // 使用 Set 提高查找效率 let visitedLinks = new Set(JSON.parse(localStorage.getItem('visitedLinks') || '[]')); // 初始化样式 function applyVisitedStyles(links) { links.forEach(link => { if (visitedLinks.has(link.href)) { link.style.setProperty('color', '#FF0000', 'important'); } }); } // 处理单个链接的函数 function handleLink(link) { const linkUrl = link.href; // 如果已访问过,直接应用样式 if (visitedLinks.has(linkUrl)) { link.style.setProperty('color', '#FF0000', 'important'); return; } // 添加点击事件监听器 link.addEventListener('click', () => { try { // 防止重复添加 if (!visitedLinks.has(linkUrl)) { visitedLinks.add(linkUrl); // 压缩存储(每100条自动清理) if (visitedLinks.size % 100 === 0) { localStorage.setItem('visitedLinks', JSON.stringify(Array.from(visitedLinks))); } // 强制应用红色样式 link.style.setProperty('color', '#FF0000', 'important'); } } catch (error) { console.error('保存记录失败:', error); alert('无法保存访问记录,请检查浏览器存储空间'); } }); } // 初始处理页面上的链接 const initialLinks = document.querySelectorAll('a'); applyVisitedStyles(initialLinks); initialLinks.forEach(handleLink); // 监控动态加载的内容 const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { // 处理新增的链接 if (node.nodeType === 1 && node.matches && node.matches('a')) { handleLink(node); applyVisitedStyles([node]); } // 递归处理子节点 Array.from(node.querySelectorAll('a')).forEach(link => { handleLink(link); applyVisitedStyles([link]); }); }); }); }); // 开始观察文档 body 的变化 observer.observe(document.body, { childList: true, subtree: true }); // 页面卸载时保存数据 window.addEventListener('beforeunload', () => { try { localStorage.setItem('visitedLinks', JSON.stringify(Array.from(visitedLinks))); } catch (error) { console.error('最后保存失败:', error); } }); // 定期备份数据 setInterval(() => { try { localStorage.setItem('visitedLinks', JSON.stringify(Array.from(visitedLinks))); } catch (error) { console.warn('定期备份失败:', error); } }, 30000); // 每30秒备份一次 })();