// ==UserScript== // @name B站个人面板美化 // @namespace http://tampermonkey.net/ // @version 1.0 // @description 磨砂面板 + 昵称拖拽布局 + HARD-CORE标签 + 深浅双主题(独立版) // @author Anonymity // @match *://*.bilibili.com/* // @grant GM_addStyle // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @run-at document-end // @license MIT // ==/UserScript== (function () { 'use strict'; // ====================== 配置 ====================== const STORAGE = { SPACE_STYLE: 'bili_space_style_enabled', TARGET_UID: 'bili_space_target_uid', CUSTOM_CONFIG: 'bili_custom_panel_config', NICKNAME_LAYOUT: 'bili_nickname_layout' }; const DEFAULT_CONFIG = { bgWatermarkNum: '6', bgRotate: -6, bgOpacityDark: 0.15, bgOpacityLight: 0.01, bgBreathAnim: true, bgFrosted: false, glassBlurDark: 12, glassBlurLight: 12, wmSizeDark: 600, wmSizeLight: 500, wmColorDark: '#B4B4B4', wmColorLight: '#505050', showHardCoreTag: true, hardCoreText: '硬核会员', hardCoreDarkBorder: '#FF69B4', hardCoreLightBorder: '#66ccff', primaryDark: '#FF69B4', primaryLight: '#66ccff' }; const DEFAULT_NICKNAME_LAYOUT = { columns: [{ id: 'col1', width: '100%', blocks: [ { id: 'b1', text: 'Sunday', x: -5, y: -10, color: '#FF69B4', fontSize: 22, rotation: -2 }, { id: 'b2', text: ' 大好き', x: 5, y: 15, color: '#FF69B4', fontSize: 20, rotation: 2 }, { id: 'b3', text: 'が', x: 40, y: 30, color: '#FF69B4', fontSize: 28, rotation: 5 } ] }] }; let spaceEnabled = GM_getValue(STORAGE.SPACE_STYLE, true); let targetUid = GM_getValue(STORAGE.TARGET_UID, '327239767'); let config = GM_getValue(STORAGE.CUSTOM_CONFIG, { ...DEFAULT_CONFIG }); config = { ...DEFAULT_CONFIG, ...config }; let nicknameLayout = GM_getValue(STORAGE.NICKNAME_LAYOUT, null); if (!nicknameLayout) { nicknameLayout = { ...DEFAULT_NICKNAME_LAYOUT }; GM_setValue(STORAGE.NICKNAME_LAYOUT, nicknameLayout); } let styleEl = null; let editorEl = null; let configPanelEl = null; let editorBackup = null; let tagInserted = false; let observer = null; // ====================== 工具 ====================== function throttle(fn, delay) { let timer = null; return (...args) => { if (!timer) { fn(...args); timer = setTimeout(() => timer = null, delay); } }; } function uid() { return 'uid_' + Math.random().toString(36).substr(2, 9); } function saveConfig() { GM_setValue(STORAGE.CUSTOM_CONFIG, config); rebuild(); } function saveLayout() { GM_setValue(STORAGE.NICKNAME_LAYOUT, nicknameLayout); applyNickname(); } // ====================== 主题检测 ====================== function getTheme() { const html = document.documentElement; const dt = html.getAttribute('data-theme'); if (dt === 'light' || dt === 'dark') return dt; if (html.classList.contains('bili_dark') || html.classList.contains('dark')) return 'dark'; if (html.classList.contains('light')) return 'light'; const ls = localStorage.getItem('bilibili_theme'); if (ls === 'light' || ls === 'dark') return ls; try { const bodyBg = getComputedStyle(document.body).backgroundColor; if (bodyBg && bodyBg !== 'rgba(0, 0, 0, 0)') { const nums = bodyBg.replace(/[^\d,]/g, '').split(',').map(Number); if (nums.length >= 3) { const brightness = nums[0] * 0.299 + nums[1] * 0.587 + nums[2] * 0.114; return brightness < 128 ? 'dark' : 'light'; } } const textColor = getComputedStyle(html).color; const tnums = textColor.replace(/[^\d,]/g, '').split(',').map(Number); if (tnums.length >= 3) { const tb = tnums[0] * 0.299 + tnums[1] * 0.587 + tnums[2] * 0.114; return tb < 128 ? 'dark' : 'light'; } } catch(e) {} return 'dark'; } function observeHtmlTheme() { const html = document.documentElement; const mo = new MutationObserver(() => applyThemeClass()); mo.observe(html, { attributes: true, attributeFilter: ['data-theme', 'class'] }); } function applyThemeClass() { const panel = document.querySelector('.avatar-panel-popover'); if (!panel) return; panel.classList.remove('theme-dark', 'theme-light'); panel.classList.add('theme-' + getTheme()); } // ====================== CSS 生成(关键修改:极透明背景 + 隐藏水印) ====================== function hex2rgb(h) { return `${parseInt(h.slice(1,3),16)},${parseInt(h.slice(3,5),16)},${parseInt(h.slice(5,7),16)}`; } function buildCSS() { const uidDark = `a.nickname-item.dark[href="//space.bilibili.com/${targetUid}"]`; const uidLight = `a.nickname-item.light[href="//space.bilibili.com/${targetUid}"]`; const { bgWatermarkNum, bgRotate, bgOpacityDark, bgOpacityLight, bgBreathAnim, bgFrosted, glassBlurDark, glassBlurLight, wmSizeDark, wmSizeLight, wmColorDark, wmColorLight, hardCoreDarkBorder, hardCoreLightBorder, primaryDark, primaryLight } = config; const pd = hex2rgb(primaryDark); const pl = hex2rgb(primaryLight); return ` /* ====== 核心变量(html data-theme 驱动) ====== */ html[data-theme="dark"] .avatar-panel-popover, html.dark .avatar-panel-popover, html.bili_dark .avatar-panel-popover { --panel-bg: rgba(16,16,22,0.04); /* 极透明 */ --panel-text: #fff; --panel-shadow: 0 2px 10px rgba(0,0,0,0.25),0 12px 40px rgba(0,0,0,0.48),inset 0 0 0 1px rgba(255,255,255,0.07); --panel-hover-shadow: 0 2px 10px rgba(0,0,0,0.25),0 12px 40px rgba(0,0,0,0.48),0 0 26px 7px rgba(${pd},0.36),inset 0 0 0 1px rgba(${pd},0.12); --logout-bg: #2E0017; --logout-hover-shadow: 0 4px 16px rgba(${pd},0.4); } html[data-theme="light"] .avatar-panel-popover, html.light .avatar-panel-popover { --panel-bg: rgba(252,252,250,0.04); /* 极透明 */ --panel-text: #2d2d2d; --panel-shadow: 0 4px 16px rgba(0,0,0,0.08),0 12px 40px rgba(0,0,0,0.15),inset 0 0 0 1px rgba(0,0,0,0.05); --panel-hover-shadow: 0 4px 16px rgba(0,0,0,0.08),0 12px 40px rgba(0,0,0,0.15),0 0 26px 7px rgba(${pl},0.36),inset 0 0 0 1px rgba(${pd},0.1); --logout-bg: linear-gradient(135deg,${primaryLight},#47b8f0); --logout-hover-shadow: 0 4px 16px rgba(${pl},0.3); } /* ====== 装饰变量(panel class 驱动) ====== */ .theme-dark.avatar-panel-popover, .avatar-panel-popover.theme-dark { --panel-bg: rgba(16,16,22,0.04); --panel-text: #fff; --panel-shadow: 0 2px 10px rgba(0,0,0,0.25),0 12px 40px rgba(0,0,0,0.48),inset 0 0 0 1px rgba(255,255,255,0.07); --panel-hover-shadow: 0 2px 10px rgba(0,0,0,0.25),0 12px 40px rgba(0,0,0,0.48),0 0 26px 7px rgba(${pd},0.36),inset 0 0 0 1px rgba(${pd},0.12); --logout-bg: #2E0017; --logout-hover-shadow: 0 4px 16px rgba(${pd},0.4); --wm-color: rgba(${hex2rgb(wmColorDark)},${bgOpacityDark}); --wm-size: ${wmSizeDark}px; --hardcore-border: ${hardCoreDarkBorder}; --item-bg: rgba(255,255,255,0.04); --item-shadow: 0 4px 12px rgba(0,0,0,0.3),0 1px 3px rgba(0,0,0,0.15); --glass-blur: ${glassBlurDark}px; --link-icon-fill: #ccc; --split-line-bg: linear-gradient(90deg,transparent,rgba(255,255,255,0.12),transparent); --level-bar-bg: #1E1E1E; --level-inner-bg: #555; --primary: ${primaryDark}; --primary-rgb: ${pd}; --avatar-shadow: drop-shadow(0 0 12px rgba(0,221,255,0.6)); --avatar-hover-shadow: drop-shadow(0 0 20px ${primaryDark}); --single-link-hover-bg: rgba(${pd},0.1); --coin-text: inherit; --coin-text-secondary: inherit; --count-hover-color: ${primaryDark}; } .theme-light.avatar-panel-popover, .avatar-panel-popover.theme-light { --panel-bg: rgba(252,252,250,0.04); --panel-text: #2d2d2d; --panel-shadow: 0 4px 16px rgba(0,0,0,0.08),0 12px 40px rgba(0,0,0,0.15),inset 0 0 0 1px rgba(0,0,0,0.05); --panel-hover-shadow: 0 4px 16px rgba(0,0,0,0.08),0 12px 40px rgba(0,0,0,0.15),0 0 26px 7px rgba(${pl},0.36),inset 0 0 0 1px rgba(${pd},0.1); --logout-bg: linear-gradient(135deg,${primaryLight},#47b8f0); --logout-hover-shadow: 0 4px 16px rgba(${pl},0.3); --wm-color: rgba(${hex2rgb(wmColorLight)},${bgOpacityLight}); --wm-size: ${wmSizeLight}px; --hardcore-border: ${hardCoreLightBorder}; --item-bg: rgba(0,0,0,0.03); --item-shadow: 0 2px 8px rgba(0,0,0,0.06),0 1px 2px rgba(0,0,0,0.04); --glass-blur: ${glassBlurLight}px; --link-icon-fill: #555; --split-line-bg: linear-gradient(90deg,transparent,rgba(0,0,0,0.06),transparent); --level-bar-bg: #E0E0E0; --level-inner-bg: #aaa; --primary: ${primaryLight}; --primary-rgb: ${pl}; --avatar-shadow: drop-shadow(0 0 12px rgba(0,221,255,0.4)); --avatar-hover-shadow: drop-shadow(0 0 20px ${primaryLight}); --single-link-hover-bg: rgba(${pd},0.08); --coin-text: #2d2d2d; --coin-text-secondary: #666; --count-hover-color: ${primaryLight}; } /* ====== panel 本体 ====== */ .avatar-panel-popover { position:relative; z-index:1; background: var(--panel-bg) !important; color: var(--panel-text) !important; box-shadow: var(--panel-shadow) !important; animation: pfPopoverFadeIn 0.25s cubic-bezier(0.2,0,0.2,1); } .avatar-panel-popover::before { content:"${bgWatermarkNum}"; position:absolute; inset:0; font-size:var(--wm-size); font-weight:bold; display:flex; align-items:center; justify-content:center; color:var(--wm-color); transform:rotate(${bgRotate}deg); user-select:none; pointer-events:none; z-index:-1; border-radius:16px; clip-path:inset(0 round 16px); ${bgBreathAnim ? 'animation:pfBgBreath 12s ease-in-out infinite;' : ''} } .avatar-panel-popover:hover { box-shadow: var(--panel-hover-shadow) !important; } .avatar-panel-popover * { -webkit-font-smoothing:antialiased !important; } ${bgFrosted ? ` /* ====== 玻璃特效 ====== */ .v-popover-content.avatar-popover, .v-popover.is-bottom { background: transparent !important; } .avatar-panel-popover { backdrop-filter: blur(var(--glass-blur)) !important; -webkit-backdrop-filter: blur(var(--glass-blur)) !important; } ` : ''} /* ====== 子元素(全用 var) ====== */ .vip-entry-containter { display:none !important; } .icon { display:none; } .senior { display:none !important; } /* 昵称 */ ${uidDark},${uidLight} { display:inline-flex !important; justify-content:space-between !important; width:85px !important; height:38px !important; font-size:0 !important; color:transparent !important; align-items:center !important; line-height:1 !important; margin:0 !important; padding:0 !important; transform:translateX(65px) translateY(-20px) !important; text-decoration:none !important; overflow:visible !important; position:relative !important; } ${uidDark}::before,${uidLight}::before, ${uidDark}::after,${uidLight}::after { content:none !important; } /* HARD-CORE */ .hard-core-tag { width:fit-content !important; margin:16px auto 20px !important; padding:5px 16px !important; border-radius:8px !important; font-size:13px !important; font-weight:500; letter-spacing:1px; white-space:nowrap; pointer-events:none; border:1px solid var(--hardcore-border) !important; color: var(--panel-text) !important; } /* 数据卡片 */ .coins-item, .counts-item { background: var(--item-bg) !important; box-shadow: var(--item-shadow) !important; border-radius:12px; } .coin-item__num, .count-num { color: var(--coin-text); } .coin-item__text, .count-text { color: var(--coin-text-secondary); } .counts-item .single-count-item { transition:all 0.3s ease; cursor:pointer; } .counts-item .single-count-item:hover { transform:scale(1.3); color: var(--count-hover-color); } .counts-item .single-count-item:hover .count-num { color: var(--count-hover-color); } /* 链接图标 */ .link-icon path { fill: var(--link-icon-fill) !important; } /* 分割线 */ .split-line { background: var(--split-line-bg) !important; } /* 退出 */ .logout-item { margin-top:16px; padding:16px; border-radius:12px; transition:all 0.3s ease; background: var(--logout-bg) !important; } .logout-item:hover { filter:brightness(1.15); transform:translateY(-2px); box-shadow: var(--logout-hover-shadow); } .logout-item span { font-size:16px; font-weight:500; letter-spacing:1px; } .theme-dark .logout-item span { color: ${primaryDark} !important; } html[data-theme="dark"] .logout-item .link-icon path, html.dark .logout-item .link-icon path, html.bili_dark .logout-item .link-icon path { fill: #fff !important; } .theme-light .logout-item span { color: #fff !important; } html[data-theme="light"] .logout-item .link-icon path, html.light .logout-item .link-icon path { fill: ${primaryLight} !important; } /* 等级条 */ .level-item { position:relative; transition:transform 0.3s ease; z-index:10; } .level-item:hover { transform:scale(1.08); } .level-progress { background: var(--level-bar-bg) !important; border-radius:3px; height:6px; overflow:visible; } .level-progress__inner { height:100%; background: var(--level-inner-bg) !important; border-radius:3px; transition:all 0.4s ease; position:relative; } .level-progress__inner::after { content:''; position:absolute; right:-10px; top:50%; transform:translateY(-50%); width:20px; height:20px; background:radial-gradient(circle,#8a2be2,transparent); opacity:0; transition:opacity 0.3s; filter:blur(2px); } .level-item:hover .level-progress__inner::after { opacity:1; } .level-item:hover .level-progress__inner { background: var(--primary); box-shadow: 0 0 10px var(--primary); } .level-intro { display:none; } /* 大头像 */ .big-avatar { margin:0 auto 12px; display:block; filter: var(--avatar-shadow); transition:all 0.3s ease; } .big-avatar:hover { transform:scale(1.05) translateY(-4px); filter: var(--avatar-hover-shadow); } /* 菜单(面板内部) */ .avatar-panel-popover .single-link-item:hover { background: var(--single-link-hover-bg) !important; border-left:3px solid var(--primary) !important; color: var(--primary); } /* 子菜单弹窗 */ .v-popover.is-right { overflow:visible; z-index:9999; } html[data-theme="dark"] .sub-links-item, html.dark .sub-links-item, html.bili_dark .sub-links-item { border-radius:12px; backdrop-filter:blur(12px); background:rgba(16,16,22,0.85); color:#fff; box-shadow:0 8px 24px rgba(0,0,0,0.4); } html[data-theme="light"] .sub-links-item, html.light .sub-links-item { border-radius:12px; backdrop-filter:blur(12px); background:rgba(252,252,250,0.88); color:#2d2d2d; box-shadow:0 8px 24px rgba(0,0,0,0.12); } html[data-theme="dark"] .sub-links-item .single-link-item:hover, html.dark .sub-links-item .single-link-item:hover, html.bili_dark .sub-links-item .single-link-item:hover { background:rgba(${pd},0.1); color:${primaryDark}; } html[data-theme="light"] .sub-links-item .single-link-item:hover, html.light .sub-links-item .single-link-item:hover { background:rgba(${pd},0.08); color:${primaryDark}; } /* 关键帧 */ @keyframes pfPopoverFadeIn { from { opacity:0; transform:translateY(-12px) scale(0.97); } to { opacity:1; transform:translateY(0) scale(1); } } @keyframes pfBgBreath { 0%,100% { opacity:0.1; } 50% { opacity:0.5; } } .level-item__bar--next:hover { animation:pfCharge 0.6s infinite ease-in-out; } @keyframes pfCharge { 0%,100% { transform:scale(1) rotate(0deg); filter:drop-shadow(0 0 5px #ff0000); } 50% { transform:scale(1.25) rotate(0deg); filter:drop-shadow(0 0 15px #ff0000); } } `; } // ====================== rebuild 等函数(无修改) ====================== function rebuild() { cleanupDOM(); if (styleEl) styleEl.remove(); styleEl = document.createElement('style'); styleEl.id = 'bili-panel-style'; styleEl.textContent = buildCSS(); document.head.appendChild(styleEl); applyThemeClass(); if (config.showHardCoreTag) insertTag(); else removeTag(); applyNickname(); } function cleanupDOM() { document.querySelectorAll('.nickname-item').forEach(el => { el.style.fontSize = ''; el.style.color = ''; }); document.querySelectorAll('.nickname-layout-container').forEach(c => c.remove()); removeTag(); } function fullCleanup() { cleanupDOM(); if (styleEl) { styleEl.remove(); styleEl = null; } tagInserted = false; } function insertTag() { if (tagInserted || !config.showHardCoreTag) return; const panel = document.querySelector('.avatar-panel-popover'); const nickEl = panel?.querySelector('.nickname-item'); const coinEl = panel?.querySelector('.coins-item'); if (!panel || !nickEl || !coinEl) return; let tag = panel.querySelector('.hard-core-tag'); if (!tag) { tag = document.createElement('div'); tag.className = 'hard-core-tag'; nickEl.parentNode.insertBefore(tag, coinEl); } tag.textContent = config.hardCoreText; tagInserted = true; } function removeTag() { const tag = document.querySelector('.hard-core-tag'); if (tag) tag.remove(); tagInserted = false; } function applyNickname() { const panel = document.querySelector('.avatar-panel-popover'); if (!panel) return; document.querySelectorAll('.nickname-layout-container').forEach(c => c.remove()); const nickItems = panel.querySelectorAll('.nickname-item.dark, .nickname-item.light'); nickItems.forEach(nickItem => { nickItem.style.fontSize = '0'; nickItem.style.color = 'transparent'; const container = document.createElement('div'); container.className = 'nickname-layout-container'; container.style.cssText = 'position:absolute; inset:0; display:flex; pointer-events:none;'; if (nicknameLayout?.columns) { nicknameLayout.columns.forEach(col => { const colDiv = document.createElement('div'); colDiv.className = 'nickname-col'; colDiv.style.cssText = `position:relative; width:${col.width}; height:100%;`; if (col.blocks) { col.blocks.forEach(block => { const span = document.createElement('span'); span.className = 'nickname-block'; span.textContent = block.text; span.style.cssText = ` position:absolute; left:${block.x}px; top:${block.y}px; color:${block.color}; font-size:${block.fontSize}px; transform:rotate(${block.rotation}deg); white-space:pre; pointer-events:none; line-height:1; font-weight:bold; `; colDiv.appendChild(span); }); } container.appendChild(colDiv); }); nickItem.appendChild(container); } }); } function toggle() { spaceEnabled = !spaceEnabled; GM_setValue(STORAGE.SPACE_STYLE, spaceEnabled); if (spaceEnabled) rebuild(); else fullCleanup(); } function updateUid() { const val = prompt('请输入目标UID(纯数字)', targetUid); if (val && /^\d+$/.test(val.trim())) { targetUid = val.trim(); GM_setValue(STORAGE.TARGET_UID, targetUid); rebuild(); } else if (val !== null) alert('UID必须为纯数字'); } // ====================== 编辑器(无修改) ====================== function openEditor() { if (editorEl) { editorEl.style.display = 'block'; return; } editorBackup = JSON.parse(JSON.stringify(nicknameLayout)); const panel = document.createElement('div'); panel.id = 'bili-nickname-editor'; panel.style.cssText = ` position:fixed; top:50px; left:50%; transform:translateX(-50%); width:700px; max-width:95vw; background:rgba(20,20,30,0.92); backdrop-filter:blur(14px); color:#fff; border-radius:14px; box-shadow:0 6px 24px rgba(0,0,0,0.5); z-index:100000; padding:16px; font-size:13px; max-height:90vh; overflow-y:auto; `; panel.innerHTML = `