// ==UserScript==
// @name Bilibili 动态美化(优化版)
// @namespace http://tampermonkey.net/
// @version 0.7
// @description 动态粉粉嫩嫩,功能:1. 美化页面;2. 隐藏个人动态发布框;3. 隐藏右侧热门话题;4. 隐藏up发布的广告动态。优化了样式注入、MutationObserver等性能问题。
// @author Water WHNI
// @match https://t.bilibili.com/*
// @match https://www.bilibili.com/
// @icon https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant GM_addStyle
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_getValue
// @license MIT
// ==/UserScript==
(function () {
'use strict';
/*** 默认设置与用户配置 ***/
const defaultSettings = {
customBackgroundURL: 'https://i0.hdslb.com/bfs/article/bfecb9a12cb9708d8d79bb9c17532e347747aeaf.jpg@1256w_708h_!web-article-pic.avif',
hideElementsEnabled: true,
hideRightSidebar: true,
hidePostBar: true,
autoFrash: true,
autoClickInterval: 5,
enableAutoClick: true,
backgroundTransparency: 61,
backgroundTransparency2: 81,
backgroundTransparencyFloat: 91
};
const settings = {};
for (const key in defaultSettings) {
settings[key] = GM_getValue(key, defaultSettings[key]);
}
/*** 合并主样式 ***/
const mainStyles = `
.bili-live-card, .floor-single-card, .adblock-tips { display: none !important; }
.bili-dyn-card-video__body, .bili-dyn-card-live__body, .bili-dyn-card-pgc__body { border: none !important; }
.bili-dyn-sidebar { right: 5vw !important; }
.bili-header__channel { background: none !important; }
.bili-dyn-up-list__item__name.bili-ellipsis,
.bili-dyn-time.fs-small,
.item-desc,
.bili-dyn-action,
.bili-dyn-more__btn,
.bili-dyn-card-video__stat__item,
#bili-header-container span,
svg { color: rgb(251, 114, 153) !important; }
.bili-dyn-interaction__item__desc .bili-rich-text__content { color: #2f3238e0 !important; }
.header-upload-entry { background-color: #fc8bab6b !important; }
.bili-dyn-more__btn:hover { background-color: #fa5a5742 !important; border-radius: 50% !important; }
.bili-dyn-card-video__desc, .bili-dyn-publishing__hint { color: #424549 !important; }
.bili-dyn-list-notification.fs-small { color: rgb(251, 114, 153) !important; }
.bili-dyn-content {
border: 2px solid transparent !important;
border-radius: 10px !important;
box-shadow: 0 0 0 rgb(251, 114, 153) !important;
transition: box-shadow 0.3s ease-in-out !important;
}
.bili-dyn-content:hover {
box-shadow: 0 0 15px rgb(251, 114, 153), 0 0 15px rgb(251, 114, 153) !important;
background-color: #ffffff80 !important;
}
.bili-dyn-up-list__item__face {
border: 1px solid transparent !important;
box-shadow: 0 0 0 rgb(251, 114, 153) !important;
transition: box-shadow 0.3s ease-in-out !important;
}
.bili-dyn-up-list__item__face:hover {
box-shadow: 0 0 5px rgb(251, 114, 153), 0 0 5px rgb(251, 114, 153) !important;
}
.bili-dyn-up-list__nav.next .bili-dyn-up-list__nav__shadow {
background: linear-gradient(90deg, hsla(0, 0%, 100%, 0), rgb(251 114 153 / 60%) !important;
}
.bili-dyn-up-list__nav__shim { background: rgb(251 114 153 / 60%) !important; }
.bili-dyn-up-list__nav.prev .bili-dyn-up-list__nav__shadow {
background: linear-gradient(270deg, hsla(0, 0%, 100%, 0), rgb(251 114 153 / 60%) !important;
}
.bili-album__watch__content { height: 30vw !important; }
.bili-album__watch__content img { height: 30vw !important; max-width: 60% !important; }
:root {
--bg1: rgba(255,255,255,${settings.backgroundTransparency / 100}) !important;
--bg2: rgba(255,255,255,${settings.backgroundTransparency2 / 100}) !important;
--bg1_float: rgba(255,255,255,${settings.backgroundTransparencyFloat / 100}) !important;
}
`;
GM_addStyle(mainStyles);
/*** 条件样式合并注入 ***/
let additionalStyles = '';
if (settings.hideRightSidebar) {
additionalStyles += `
.right { display: none !important; }
#app > div.bili-dyn-home--member > main { width: 70vw !important; }
`;
}
if (settings.hidePostBar) {
additionalStyles += `
.bili-dyn-publishing { display: none !important; }
#app > div.bili-dyn-home--member > main > section:nth-child(1) { display: none !important; }
.bili-dyn-up-list__window { padding: 20px 0 !important; margin-top: 2px !important; }
`;
}
if (additionalStyles) {
GM_addStyle(additionalStyles);
}
/*** 样式节点复用:背景图 & 背景透明度 ***/
const bgImageStyleEl = GM_addStyle(''); // 用于背景图样式
const updateBackgroundImage = (url) => {
bgImageStyleEl.innerHTML = `
.bg {
background-image: url("${url}") !important;
background-size: cover !important;
background-attachment: fixed !important;
background-position: center center !important;
background-repeat: no-repeat !important;
height: 100% !important;
}
`;
};
updateBackgroundImage(settings.customBackgroundURL);
const transparencyStyleEl = GM_addStyle(''); // 用于透明度变量
const updateTransparency = (transparency, tB2, bg1F) => {
transparencyStyleEl.innerHTML = `
:root {
--bg1: rgba(255,255,255,${transparency/100}) !important;
--bg2: rgba(255,255,255,${tB2/100}) !important;
--bg1_float: rgba(255,255,255,${bg1F/100}) !important;
}
`;
};
updateTransparency(settings.backgroundTransparency, settings.backgroundTransparency2, settings.backgroundTransparencyFloat);
/*** 隐藏广告动态的逻辑(加入防抖处理) ***/
const hideSpecificElements = () => {
document.querySelectorAll('.bili-dyn-list__item').forEach(item => {
if (item.querySelector('.bili-rich-text-module.goods')) {
item.style.display = 'none';
}
});
};
// 简单防抖函数
const debounce = (fn, delay) => {
let timer;
return (...args) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
};
const debouncedHide = debounce(hideSpecificElements, 100);
if (settings.hideElementsEnabled) {
hideSpecificElements();
new MutationObserver(debouncedHide).observe(document.body, { childList: true, subtree: true });
}
/*** 定时自动点击“加载新动态” ***/
const checkAndClick = () => {
const selector = '#app > div.bili-dyn-home--member > main > section:nth-child(3) > div.bili-dyn-list > div.bili-dyn-list__notification > div';
const element = document.querySelector(selector);
if (element) {
try {
element.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));
} catch (e) {
const event = document.createEvent('Event');
event.initEvent('click', true, true);
element.dispatchEvent(event);
}
}
};
let autoClickIntervalId;
const setupAutoClick = () => {
if (settings.enableAutoClick) {
autoClickIntervalId = setInterval(checkAndClick, settings.autoClickInterval * 1000);
}
};
setupAutoClick();
/*** 菜单与交互设置(基本逻辑保持不变) ***/
const createToggle = (label, key) => {
const container = document.createElement('div');
container.style.cssText = `
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
`;
const toggleLabel = document.createElement('label');
toggleLabel.innerText = label;
toggleLabel.style.margin = '0';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.checked = settings[key];
checkbox.style.marginLeft = '10px';
checkbox.onchange = () => settings[key] = checkbox.checked;
container.append(toggleLabel, checkbox);
return { container, checkbox };
};
GM_registerMenuCommand('设置', () => {
const modal = document.createElement('div');
modal.style.cssText = `
position: fixed;
top: 8vh;
right: 1vw;
padding: 20px;
background-color: #fff;
box-shadow: 0 0 15px rgba(0, 0, 0, 0.3);
border-radius: 10px;
z-index: 9999;
width: 320px;
font-family: Arial, sans-serif;
overflow: auto;
`;
const modalHeader = document.createElement('div');
modalHeader.style.cssText = `
font-size: 20px;
font-weight: bold;
margin-bottom: 15px;
text-align: center;
`;
modalHeader.innerText = '设置';
// 背景图片输入及应用
const bgInputContainer = document.createElement('div');
bgInputContainer.style.cssText = `
display: flex;
align-items: center;
margin-bottom: 10px;
width: 100%;
`;
const bgInputLabel = document.createElement('label');
bgInputLabel.innerText = '背景图片URL: ';
bgInputLabel.style.flex = '0 0 35%';
const bgInput = document.createElement('input');
bgInput.type = 'text';
bgInput.value = settings.customBackgroundURL;
bgInput.style.cssText = `
flex: 1;
padding: 5px;
border: 1px solid #ccc;
border-radius: 5px;
margin-left: 10px;
overflow: hidden;
text-overflow: ellipsis;
`;
const applyBgButton = document.createElement('button');
applyBgButton.innerText = '应用';
applyBgButton.style.cssText = `
width: 100%;
padding: 5px 10px;
background-color: #12a9df;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
margin-bottom: 5px;
`;
applyBgButton.onclick = () => {
const newURL = bgInput.value;
GM_setValue('customBackgroundURL', newURL);
updateBackgroundImage(newURL);
};
bgInputContainer.append(bgInputLabel, bgInput);
// 创建开关
const { container: hideUpAdContainer, checkbox: hideUpAdCheckbox } = createToggle('隐藏UP广告动态', 'hideElementsEnabled');
const { container: hideSidebarContainer, checkbox: hideSidebarCheckbox } = createToggle('隐藏右边栏', 'hideRightSidebar');
const { container: hidePostBarContainer, checkbox: hidePostBarCheckbox } = createToggle('隐藏动态发布', 'hidePostBar');
const { container: timerToggleContainer, checkbox: timerToggleCheckbox } = createToggle('自动加载新动态', 'enableAutoClick');
// 点击间隔输入框
const intervalContainer = document.createElement('div');
intervalContainer.style.cssText = `
display: flex;
align-items: center;
margin-bottom: 10px;
width: 100%;
`;
const intervalLabel = document.createElement('label');
intervalLabel.innerText = '点击间隔 (秒): ';
intervalLabel.style.flex = '0 0 35%';
const intervalInput = document.createElement('input');
intervalInput.type = 'number';
intervalInput.min = '1';
intervalInput.value = settings.autoClickInterval || 5;
intervalInput.style.cssText = `
flex: 1;
padding: 5px;
margin-left: 10px;
border: 1px solid #ccc;
border-radius: 5px;
`;
intervalInput.oninput = () => {
const interval = Math.max(1, parseInt(intervalInput.value));
settings.autoClickInterval = interval;
GM_setValue('autoClickInterval', interval);
if (settings.enableAutoClick) {
clearInterval(autoClickIntervalId);
autoClickIntervalId = setInterval(checkAndClick, interval * 1000);
}
};
intervalContainer.append(intervalLabel, intervalInput);
// 背景透明度滑块
const sliderContainer = document.createElement('div');
sliderContainer.style.cssText = `
display: flex;
align-items: center;
margin-bottom: 10px;
width: 100%;
`;
const sliderLabel = document.createElement('label');
sliderLabel.innerText = '背景透明度: ';
sliderLabel.style.flex = '0 0 35%';
const slider = document.createElement('input');
slider.type = 'range';
slider.min = '0';
slider.max = '100';
slider.value = settings.backgroundTransparency;
slider.style.cssText = `
flex: 1;
margin-left: 5px;
`;
slider.oninput = () => {
const transparency = parseInt(slider.value);
settings.backgroundTransparency2 = Math.min(transparency + 20, 100);
settings.backgroundTransparencyFloat = Math.min(transparency + 50, 100);
GM_setValue('backgroundTransparency', transparency);
GM_setValue('backgroundTransparency2', settings.backgroundTransparency2);
GM_setValue('backgroundTransparencyFloat', settings.backgroundTransparencyFloat);
updateTransparency(transparency, settings.backgroundTransparency2, settings.backgroundTransparencyFloat);
};
sliderContainer.append(sliderLabel, slider);
// 按钮容器
const buttonContainer = document.createElement('div');
buttonContainer.style.cssText = `
display: flex;
justify-content: space-between;
margin-top: 15px;
`;
const closeButton = document.createElement('button');
closeButton.innerText = '关闭';
closeButton.style.cssText = `
padding: 5px 10px;
background-color: #f44336;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
`;
closeButton.onclick = () => document.body.removeChild(modal);
const saveButton = document.createElement('button');
saveButton.innerText = '保存';
saveButton.style.cssText = `
padding: 5px 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
`;
saveButton.onclick = () => {
GM_setValue('hideElementsEnabled', hideUpAdCheckbox.checked);
GM_setValue('hideRightSidebar', hideSidebarCheckbox.checked);
GM_setValue('hidePostBar', hidePostBarCheckbox.checked);
GM_setValue('enableAutoClick', timerToggleCheckbox.checked);
GM_setValue('autoClickInterval', Math.max(1, parseInt(intervalInput.value)));
location.reload();
};
buttonContainer.append(saveButton, closeButton);
modal.append(
modalHeader,
bgInputContainer, applyBgButton,
hideUpAdContainer,
hideSidebarContainer,
hidePostBarContainer,
timerToggleContainer,
intervalContainer,
sliderContainer,
buttonContainer
);
document.body.appendChild(modal);
});
})();