// ==UserScript== // @name 多模式护眼助手 // @version 5.0 // @description 脚本菜单支持多种护眼模式切换,背景与链接颜色配套,支持自定义域名禁用。 // @author Gemini // @run-at document-start // @match *://*/* // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @namespace https://greasyfork.org/users/452911 // @downloadURL https://update.greasyfork.icu/scripts/460539/%E5%A4%9A%E6%A8%A1%E5%BC%8F%E6%8A%A4%E7%9C%BC%E5%8A%A9%E6%89%8B.user.js // @updateURL https://update.greasyfork.icu/scripts/460539/%E5%A4%9A%E6%A8%A1%E5%BC%8F%E6%8A%A4%E7%9C%BC%E5%8A%A9%E6%89%8B.meta.js // ==/UserScript== (function() { 'use strict'; // 1. 配置中心:颜色配套方案 const THEMES = { 'default': { name: '豆沙绿', bg: '#C7EDCC', link: '#2E7D32' }, 'parchment': { name: '羊皮纸', bg: '#F4ECD8', link: '#8B4513' }, 'pink': { name: '樱花粉', bg: '#FDE2E4', link: '#C2185B' }, 'cyan': { name: '青草蓝', bg: '#DCEFF0', link: '#006064' }, 'warm': { name: '暖阳黄', bg: '#FAF9DE', link: '#E65100' } }; let currentMode = GM_getValue('currentMode', 'default'); const currentDomain = window.location.hostname; let disabledDomains = GM_getValue('disabledDomains', []); let isDisabled = disabledDomains.includes(currentDomain); // 2. 注入动态 CSS 变量控制中心 const styleEl = document.createElement('style'); styleEl.id = 'eye-protector-core-style'; // 在 head 还没加载出来时,注入到 documentElement (document.head || document.documentElement).appendChild(styleEl); function updateCSSVars(modeKey) { if (isDisabled) { styleEl.textContent = ''; return; } const theme = THEMES[modeKey] || THEMES.default; styleEl.textContent = ` :root { --eye-bg: ${theme.bg} !important; --eye-link: ${theme.link} !important; } /* 只有被打上标记的元素才会变色 */ [data-eye-bg="true"] { background-color: var(--eye-bg) !important; background-image: none !important; } [data-eye-link="true"] { color: var(--eye-link) !important; text-decoration: none !important; } `; } // 3. 元素扫描与标记引擎 function scanAndTag() { if (isDisabled) return; // 获取所有尚未被本脚本扫描过的元素 const elements = document.querySelectorAll('*:not([data-eye-scanned])'); elements.forEach(el => { el.setAttribute('data-eye-scanned', 'true'); // A. 排除项:视频、图片、画板、图标 if (el.matches('video, img, canvas, svg, [class*="player"], .icon, .fa')) return; // B. 链接处理 if (el.tagName === 'A') { el.setAttribute('data-eye-link', 'true'); } // C. 背景处理:针对原脚本提到的特殊 ID 和 类名 进行强制覆盖 if (el.matches('DIV#gb-main, DIV.url.clearfix, DIV.nav-bar-v2-fixed, DIV.se-page-hd-content')) { el.setAttribute('data-eye-bg', 'true'); return; } // D. 智能背景判定:如果是浅色背景,则标记 const style = window.getComputedStyle(el); const bgColor = style.backgroundColor; const rgb = bgColor.match(/\d+/g); if (rgb && rgb.length >= 3) { const [r, g, b] = rgb.map(Number); // 判定阈值:RGB 均大于 220 通常为白色或近白色背景 if (r > 220 && g > 220 && b > 220) { el.setAttribute('data-eye-bg', 'true'); } } }); } // 4. 注册脚本菜单 function initMenus() { // 开关切换 GM_registerMenuCommand(isDisabled ? "🟢 开启当前网站护眼" : "🔴 禁用当前网站护眼", () => { if (isDisabled) { disabledDomains = disabledDomains.filter(d => d !== currentDomain); } else { disabledDomains.push(currentDomain); } GM_setValue('disabledDomains', disabledDomains); location.reload(); // 涉及域名白名单,建议刷新以重置所有样式 }); // 颜色模式切换(无需刷新) Object.keys(THEMES).forEach(key => { GM_registerMenuCommand("🎨 模式:" + THEMES[key].name, () => { currentMode = key; GM_setValue('currentMode', key); updateCSSVars(key); console.log(`已切换至: ${THEMES[key].name}`); }); }); } // 5. 启动逻辑 updateCSSVars(currentMode); initMenus(); // 持续监听:处理动态加载、瀑布流、弹窗等新元素 const observer = new MutationObserver(() => { scanAndTag(); }); // 监听文档变化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { observer.observe(document.body, { childList: true, subtree: true }); scanAndTag(); }); } else { observer.observe(document.body, { childList: true, subtree: true }); scanAndTag(); } // 兜底:处理某些特殊加载情况 window.addEventListener('load', scanAndTag); })();