// ==UserScript== // @name nodeseek论坛美化 // @description nodeseek论坛美化,支持多种背景主题切换 // @author kitawa // @version 0.2 // @match https://www.nodeseek.com/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @license MIT // @namespace http://tampermonkey.net/ // @run-at document-start // @downloadURL https://update.greasyfork.icu/scripts/535744/nodeseek%E8%AE%BA%E5%9D%9B%E7%BE%8E%E5%8C%96.user.js // @updateURL https://update.greasyfork.icu/scripts/535744/nodeseek%E8%AE%BA%E5%9D%9B%E7%BE%8E%E5%8C%96.meta.js // ==/UserScript== // 配置项 const CONFIG = { TRANSITION_DELAY: 200, // 页面显示延迟时间(毫秒) TRANSITION_DURATION: 500, // 过渡动画持续时间(毫秒) }; // 初始化页面隐藏样式(防止闪烁) (function hookBody() { // 获取当前选中的背景索引(如果不存在,则默认为0) const savedBgIndex = GM_getValue('nodeseek_bg_index', 0); const bgClass = `bg${savedBgIndex + 1}`; // 创建一个样式表,包含淡入动画和背景预加载样式 const initialHideStyle = document.createElement("style"); initialHideStyle.textContent = ` body { opacity: 0 !important; visibility: hidden !important; } body.script-ready { opacity: 1 !important; visibility: visible !important; transition: opacity ${CONFIG.TRANSITION_DURATION}ms ease; } `; // 单独创建一个预加载背景样式表,确保样式立即生效 const preloadStyle = document.createElement("style"); preloadStyle.id = "nodeseek-preload-style"; // 为不同的背景类型创建不同的预加载样式 if (bgClass === 'bg1') { preloadStyle.textContent = ` html, body { background-attachment: fixed !important; background-image: radial-gradient(at 40% 20%, hsla(28,73%,62%,.5) 0px, transparent 50%), radial-gradient(at 80% 0%, hsla(215,93%,62%,.5) 0px, transparent 40%), radial-gradient(at 0% 50%, hsla(355,93%,62%,.5) 0px, transparent 70%), radial-gradient(at 80% 50%, hsla(340,73%,62%,.5) 0px, transparent 70%), radial-gradient(at 0% 100%, hsla(300,43%,62%,.6) 0px, transparent 50%), radial-gradient(at 80% 100%, hsla(260,73%,62%,.5) 0px, transparent 50%), radial-gradient(at 0% 0%, hsla(390,83%,62%,.5) 0px, transparent 50%) !important; background-size: 100% 100% !important; } `; } else if (bgClass === 'bg2') { preloadStyle.textContent = ` html, body { background-attachment: fixed !important; background-image: radial-gradient(at 25% 20%, hsla(195, 80%, 65%, 0.5) 0px, transparent 50%), radial-gradient(at 75% 15%, hsla(235, 55%, 70%, 0.5) 0px, transparent 50%), radial-gradient(at 15% 60%, hsla(215, 55%, 60%, 0.5) 0px, transparent 50%), radial-gradient(at 85% 70%, hsla(180, 80%, 64%, 0.3) 0px, transparent 100%), radial-gradient(at 40% 90%, hsla(265, 50%, 68%, 0.5) 0px, transparent 150%), radial-gradient(at 60% 10%, hsla(345, 50%, 62%, 0.5) 0px, transparent 50%), radial-gradient(at 50% 50%, hsla(220, 50%, 66%, 0.5) 0px, transparent 50%) !important; background-size: 110% 100% !important; } `; } else if (bgClass === 'bg3') { preloadStyle.textContent = ` html, body { background-attachment: fixed !important; background-color: rgba(200, 204, 208, 0.9) !important; background-image: none !important; } `; } else if (bgClass === 'bg4') { preloadStyle.textContent = ` html, body { background-attachment: fixed !important; background-color: rgba(140, 180, 190, 0.5) !important; } `; } // 添加样式表到head document.head.appendChild(initialHideStyle); document.head.appendChild(preloadStyle); // 预先添加背景类到HTML元素 document.documentElement.classList.add(bgClass); // 页面加载完成后监听body元素创建,添加背景类 const observer = new MutationObserver((mutations) => { if (document.body) { document.body.classList.add(bgClass); observer.disconnect(); } }); observer.observe(document.documentElement, { childList: true, subtree: true }); if (CONFIG.DEBUG) console.log('[平滑显示] 页面初始化隐藏样式和背景预加载已注入'); })(); (function () { 'use strict'; // 辅助函数:将驼峰命名转换为短横线命名 function camelToKebab(str) { return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`); } // 定义背景选项 const backgroundOptions = [ { id: 'bg1', name: '背景1', styles: { backgroundImage: ` radial-gradient(at 40% 20%, hsla(28,73%,62%,.5) 0px, transparent 50%), radial-gradient(at 80% 0%, hsla(215,93%,62%,.5) 0px, transparent 40%), radial-gradient(at 0% 50%, hsla(355,93%,62%,.5) 0px, transparent 70%), radial-gradient(at 80% 50%, hsla(340,73%,62%,.5) 0px, transparent 70%), radial-gradient(at 0% 100%, hsla(300,43%,62%,.6) 0px, transparent 50%), radial-gradient(at 80% 100%, hsla(260,73%,62%,.5) 0px, transparent 50%), radial-gradient(at 0% 0%, hsla(390,83%,62%,.5) 0px, transparent 50%) `, backgroundSize: '100% 100% !important', } }, { id: 'bg2', name: '背景2', styles: { backgroundImage: `radial-gradient(at 25% 20%, hsla(195, 80%, 65%, 0.5) 0px, transparent 50%), /* 冷:湖蓝 */ radial-gradient(at 75% 15%, hsla(235, 55%, 70%, 0.5) 0px, transparent 50%), /* 冷:紫蓝 */ radial-gradient(at 15% 60%, hsla(215, 55%, 60%, 0.5) 0px, transparent 50%), /* 冷:亮蓝 */ radial-gradient(at 85% 70%, hsla(180, 80%, 64%, 0.3) 0px, transparent 100%), /* 冷:青 */ radial-gradient(at 40% 90%, hsla(265, 50%, 68%, 0.5) 0px, transparent 150%), /* 冷:深紫蓝 */ radial-gradient(at 60% 10%, hsla(345, 50%, 62%, 0.5) 0px, transparent 50%), /* 暖:玫红(点缀) */ radial-gradient(at 50% 50%, hsla(220, 50%, 66%, 0.5) 0px, transparent 50%)`, backgroundSize: '110% 100%', } }, { id: 'bg3', name: '背景3', styles: { backgroundColor: 'rgba(200, 204, 208, 0.9)', backgroundImage: 'none', } }, { id: 'bg4', name: '背景4', styles: { backgroundColor: 'rgba(140, 180, 190, 0.5)', } } ]; // 获取当前选中的背景索引(如果不存在,则默认为0) const currentBgIndex = GM_getValue('nodeseek_bg_index', 0); // 创建和插入基础样式(立即执行,不依赖DOM) const baseStyle = document.createElement('style'); baseStyle.id = "nodeseek-base-style"; baseStyle.type = 'text/css'; baseStyle.innerHTML = ` .bg1, .bg2, .bg3, .bg4 { background-attachment: fixed !important; } .bg1 { ${Object.entries(backgroundOptions[0].styles).map(([key, value]) => `${camelToKebab(key)}: ${value};`).join('\n ')} } .bg2 { ${Object.entries(backgroundOptions[1].styles).map(([key, value]) => `${camelToKebab(key)}: ${value};`).join('\n ')} } .bg3 { ${Object.entries(backgroundOptions[2].styles).map(([key, value]) => `${camelToKebab(key)}: ${value};`).join('\n ')} } .bg4 { ${Object.entries(backgroundOptions[3].styles).map(([key, value]) => `${camelToKebab(key)}: ${value};`).join('\n ')} } /* 背景切换器样式 */ .bg-switcher { position: fixed; bottom: 10px; right: 10px; display: flex; gap: 15px; z-index: 9999; padding: 15px 8px; border-radius: 30px !important; background-color: rgba(255, 255, 255, 0.5); backdrop-filter: blur(5px); box-shadow: 0 1px 12px rgba(0, 0, 0, 0); transition: all 0.3s ease; opacity: 1; flex-direction: column; align-items: center; } .bg-switcher:hover { opacity: 1; background-color: rgba(255, 255, 255, 0.4); } .bg-option { width: 10px; height: 10px; border-radius: 50% !important; cursor: pointer; transition: all 0.3s ease; position: relative; } .bg-option:hover { transform: scale(1.2); } .bg-option.active { outline: 1px solid #ffffff; background: #63CA56 !important; } .bg-option::after { content: attr(title); position: absolute; top: -5px; right: 10%; transform: translateX(0%) scale(0); background-color: rgba(0, 0, 0, 0.5); color: white; padding: 2px 8px; border-radius: 6px; font-size: 10px; white-space: nowrap; opacity: 0; transition: all 0.3s ease; pointer-events: none; } .bg-option:hover::after { opacity: 1; transform: translateX(-50%) scale(1); } #bg-option-3, #bg-option-2, #bg-option-1, #bg-option-0 { background: rgba(0, 0, 0, 0.20); } /*-------主页----------*/ :root { --bg-main-color: rgba(255, 255, 255, 0.5); } a { color: #333; } header { box-shadow: none !important; border-bottom: 1px solid rgba(255, 255, 255, 0.3); } #nsk-head { height: 50px; } header .beta-icon { color: rgba(0, 0, 0, 0.5); } #nsk-head .nav-menu { font-weight: bold !important; } .pure-form input[type="color"], .pure-form input[type="date"], .pure-form input[type="datetime-local"], .pure-form input[type="datetime"], .pure-form input[type="email"], .pure-form input[type="month"], .pure-form input[type="number"], .pure-form input[type="password"], .pure-form input[type="search"], .pure-form input[type="tel"], .pure-form input[type="text"], .pure-form input[type="time"], .pure-form input[type="url"], .pure-form input[type="week"], .pure-form select, .pure-form textarea { padding: 0.5em 0.6em; border: none; box-shadow: none; border-radius: 8px; } .topic-carousel-item[data-v-46eb9878] { border-bottom: none !important; padding-bottom: 15px !important; } .topic-carousel-panel[data-v-46eb9878] { min-height: 100px !important; } .topic-carousel-index-item[data-v-46eb9878] { visibility: visible; } .nsk-badge.read-only { border-radius: 6px; } #nsk-body-left .sorter { background-color: transparent; border: 1px solid rgba(0, 0, 0, 0.8); border-radius: 6px; display: inline-flex; height: 22px; line-height: 22px; } #nsk-body-left .sorter > a { background-color: #fff; } #nsk-body-left .sorter > a.selected { background-color: #000; color: #fff; } #nsk-body-left .post-list .post-list-item .post-title { font-weight: 500; font-size: 14px; color: #333; } #nsk-body { background-color: rgba(255, 255, 255, 0.5); border: 1px solid rgba(255, 255, 255, 0.3); box-shadow: 0 1px 20px rgba(0, 0, 0, 0.10); } #nsk-body-left .post-list .post-list-item { border-bottom: none; display: flex; margin: 10px 0; position: relative; background: rgba(255, 255, 255, 0.8); border-radius: 10px; padding: 15px; align-items: center; border: 1px solid rgba(255, 255, 255); } #nsk-body-left .post-list .post-list-item .post-category { background: rgba(0, 0, 0, 0.8); box-shadow: none; color: #fff; padding: 1px 10px; border-radius: 8px; } .nsk-content-meta-info .is-poster { border: 0px solid #00eaff; color: orangered; } .post-list-item:hover { background: rgba(0, 0, 0, 0.05); border-radius: 12px; } .promotation-item img { border-radius: 10px !important; } .user-card .user-stat a[data-v-0f04b1f4] { color: #333; font-size: 12px; font-weight: 500; } #nsk-body-left .post-list .post-list-item .post-category { bottom: 30px; } .avatar-normal { box-shadow: none; border: 2px solid #000 !important; border-radius: 10px; } #nsk-body-left .post-list .post-list-item .post-list-content { margin-left: 10px; word-wrap: break-word; width: 600px; } .carousel-mask[data-v-46eb9878] { background: transparent; } footer { background-color: rgba(0, 0, 0, 0.6); } /*-------侧边栏----------*/ .new-discussion { margin-bottom: 0; width: 100%; height: 40px; line-height: 38px; border-radius: 10px; font-size: 15px; } .user-card .user-stat .stat-block div[data-v-0f04b1f4]:nth-last-child(n+2) { margin-bottom: 12px; } .user-card .user-stat[data-v-0f04b1f4] { background-color: rgba(255, 255, 255, 0.8); box-shadow: none; border: 1px solid rgba(255, 255, 255); border-radius: 10px !important; padding: 15px; display: flex; color: #333; margin: 5px 0 20px; } #nsk-right-panel-container .nsk-panel ul li:nth-last-child(n+2) { border-bottom: none; } #nsk-right-panel-container .nsk-panel ul li { height: 30px; line-height: 30px; padding-left: 10px; } #nsk-right-panel-container .nsk-panel { box-shadow: none !important; color: #333; border-radius: 10px !important; margin: 20px 0 20px; padding: 15px 10px !important; background: rgba(255, 255, 255, 0.8); border: 1px solid rgba(255, 255, 255); } #nsk-right-panel-container > div.user-card > div.user-head > a > img { height: 60px; width: 60px; border: 3px solid #000 !important; } /*-------内页----------*/ .nsk-post-wrapper .content-item { border-bottom: none; padding: 20px; border: 1px solid rgba(255, 255, 255); position: relative; background: rgba(255, 255, 255, 0.8); margin: 15px 0; border-radius: 10px; } .nsk-post-wrapper .floor-link-wrapper { position: absolute; right: 20px; } .comment-menu .menu-item[data-v-372de460] { color: #999; margin-right: 15px; cursor: pointer; transition: all 0.3s ease; } .signature a { color: #55b786; font-size: 12px; } .post-content blockquote { border-radius: 10px; border-left: none; } .post-content pre { background: #fae6873b; border: 4px solid #c2bb983b; border-radius: 10px; padding: 8px; } .nav-item-btn { background-color: rgba(255, 255, 255, 0.7); backdrop-filter:blur(20px); border: none; width: 30px; border: 1px solid rgba(255, 255, 255, 0.3); box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1), inset 0px 0px 15px 0px rgba(255, 255, 255, 0.5) !important; } .nav-item-btn .iconpark-icon { height: 16px !important; width: 16px !important; } .nsk-pager .pager-pos.pager-cur { background-color: rgba(0, 0, 0, 0.8)!important; box-shadow: none; color: #fff; border-radius: 50%; font-size: 12px; } .nsk-pager .pager-next, .nsk-pager .pager-pos, .nsk-pager .pager-prev { color: #333; font-size: 12px; } .nsk-pager a, .nsk-pager span { border: none; margin: 0 2px; } .triangle-left, .triangle-right { border-color: transparent transparent #555; border-width: 0 4px 8px; } .signature { border-top: 1px dashed #e2e2e2; padding-top: 5px; } .signature > * { margin: 2px; color: #666 !important; font-size: 12px !important; font-weight: 400 !important; } .signature a { color: #666 !important; } .nsk-content-meta-info .author-name { font-size: 14px; font-weight: 700 !important; } a, abbr, acronym, address, applet, big, caption, cite, dd, del, dfn, div, dl, dt, em, fieldset, font, form, html, iframe, img, ins, kbd, label, legend, li, object, ol, q, s, samp, small, span, strike, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, ul, var { font-style: normal; } .signature a:hover { color: #333; } .post-content a { color: #80bcbd; } .nsk-panel > div { padding: 15px 0 !important; } .post-content img { box-shadow: none; border-radius: 12px; border: 4px solid rgba(0, 0, 0, 0.2); } .post-content a[href^="/member?t="] { color: #51829b; font-style: normal; } .post-content code { background: #faf5df; padding: 0 3px; border: 1px solid rgb(232, 228, 208); border-radius: 4px; } /*-------回复----------*/ .md-editor[data-v-2664b64e] { margin: 30px 8px; border-radius: 5px; box-shadow: 0 0 3px rgba(0, 0, 0, 0.3); background-color: var(--bg-sub-color); height: unset !important; border-radius: 8px; overflow: hidden; } /*-------个人主页----------*/ .head-container .avatar-wrapper .setting-icon { display: none; } .head-container .avatar[data-v-18f8c01b] { border: 4px solid rgba(0, 0, 0); border-radius: 20px; } .readme[data-v-18f8c01b] { box-shadow: none; background-color: rgba(255, 255, 255, 0.8); border: 1px solid rgba(255, 255, 255, 0.3); border-radius: 12px; } .selector[data-v-18f8c01b] { box-shadow: none; background-color: rgba(255, 255, 255, 0.5); border: 1px solid rgba(255, 255, 255, 0.3); } .head-container[data-v-18f8c01b] { box-shadow: none; background-color: rgba(255, 255, 255, 0.5); border: 1px solid rgba(255, 255, 255, 0.3); } `; document.documentElement.appendChild(baseStyle); // 设置初始背景样式 const setInitialBackground = () => { if (document.body) { // 直接调用更新背景函数,确保和点击切换时使用相同的逻辑 updateBackground(currentBgIndex); return true; } return false; }; // 添加背景切换器 const addBackgroundSwitcher = () => { if (document.body) { if (!document.querySelector('.bg-switcher')) { const bgSwitcher = document.createElement('div'); bgSwitcher.className = 'bg-switcher'; // 创建4个选项按钮 backgroundOptions.forEach((option, index) => { const bgOption = document.createElement('div'); bgOption.className = `bg-option ${index === currentBgIndex ? 'active' : ''}`; bgOption.id = `bg-option-${index}`; bgOption.setAttribute('title', option.name); // 添加点击事件 bgOption.addEventListener('click', () => { // 更新活动状态 document.querySelectorAll('.bg-option').forEach(opt => opt.classList.remove('active')); bgOption.classList.add('active'); // 更新背景样式 (会自动保存到GM_setValue) updateBackground(index); }); bgSwitcher.appendChild(bgOption); }); document.body.appendChild(bgSwitcher); } return true; } return false; }; // 创建和管理动态样式表 const createDynamicStyleSheet = (() => { let styleSheet = null; return () => { if (!styleSheet) { // 创建新的样式表元素 const style = document.createElement('style'); style.id = 'nodeseek-dynamic-style'; document.head.appendChild(style); styleSheet = style.sheet; } return styleSheet; }; })(); // 更新背景样式 const updateBackground = (index) => { // 获取目标背景选项 const bgOption = backgroundOptions[index]; // 1. 移除元素上的所有背景类 document.body.classList.remove('bg1', 'bg2', 'bg3', 'bg4'); document.documentElement.classList.remove('bg1', 'bg2', 'bg3', 'bg4'); // 2. 添加新的背景类 document.body.classList.add(bgOption.id); document.documentElement.classList.add(bgOption.id); // 3. 使用强制刷新来应用背景更改 const styleSheet = createDynamicStyleSheet(); // 清空现有规则 while (styleSheet.cssRules.length > 0) { styleSheet.deleteRule(0); } // 添加新的样式规则 const styleText = ` body.${bgOption.id}, html.${bgOption.id} { ${Object.entries(bgOption.styles).map(([key, value]) => `${camelToKebab(key)}: ${value} !important;`).join('\n ')} background-attachment: fixed !important; } `; styleSheet.insertRule(styleText, 0); // 4. 保存到本地存储,供下次页面切换使用 GM_setValue('nodeseek_bg_index', index); // 5. 触发重绘 void document.documentElement.offsetHeight; }; // 初始化函数 const init = () => { // 移除预加载样式 const preloadStyle = document.getElementById('nodeseek-preload-style'); if (preloadStyle) { preloadStyle.remove(); } // 设置初始背景 if (!setInitialBackground()) { const bodyObserver = new MutationObserver(() => { if (setInitialBackground()) { bodyObserver.disconnect(); } }); bodyObserver.observe(document.documentElement, { childList: true, subtree: true }); } // 添加背景切换器 if (!addBackgroundSwitcher()) { const switcherObserver = new MutationObserver(() => { if (addBackgroundSwitcher()) { switcherObserver.disconnect(); } }); switcherObserver.observe(document.documentElement, { childList: true, subtree: true }); } // 页面准备完成,添加class使页面显示 setTimeout(() => { document.body.classList.add('script-ready'); }, CONFIG.TRANSITION_DELAY); // 使用配置的延迟时间 }; // 运行初始化 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();