极致纯净的 Bing 搜索体验。修复内容消失问题,卡片式布局,强力去广告,自定义背景,完美居中。
// ==UserScript==
// @name Bing Zen Mode (2025 Evolution) - 极致美化/修复内容消失
// @namespace http://tampermonkey.net/
// @version 10.0
// @description 极致纯净的 Bing 搜索体验。修复内容消失问题,卡片式布局,强力去广告,自定义背景,完美居中。
// @author Gemini & User
// @match https://www.bing.com/search*
// @match https://cn.bing.com/search*
// @match https://www4.bing.com/search*
// @grant GM_addStyle
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @run-at document-start
// ==/UserScript==
(function() {
'use strict';
// ================= 配置中心 =================
const CONFIG = {
KEY_BG: 'bing_zen_bg_v2',
KEY_BLOCK: 'bing_zen_block_v2',
// 默认背景:清新海景
DEFAULT_BG: 'https://raw.githubusercontent.com/WJH-makers/markdown_photos/main/images/sea.png',
// 核心容器宽度
CONTAINER_WIDTH: '800px'
};
// ================= 样式注入 (核心修复逻辑) =================
function injectStyles(bgImage) {
const css = `
:root {
--zen-bg: url('${bgImage}');
--glass-card: rgba(255, 255, 255, 0.85);
--glass-border: 1px solid rgba(255, 255, 255, 0.6);
--shadow-soft: 0 8px 32px rgba(0, 0, 0, 0.08);
--text-primary: #333;
--text-secondary: #5f6368;
--accent-color: #0078d4;
}
/* === 全局重置 === */
body {
background: var(--zen-bg) center/cover fixed no-repeat !important;
min-height: 100vh;
overflow-x: hidden;
}
/* 隐藏原生背景和干扰元素 */
#b_results > .b_top,
#id_sc, #b_header .b_scopebar,
.b_footer, #b_footer,
.b_ans.b_mop, .b_ad, .sb_adsWv2,
#b_context, #b_pole, .rs-container,
#rw_crs, .b_rs, #rso_td,
.b_entityTP, .b_ans.b_top {
display: none !important;
}
/* === 顶部搜索栏 (悬浮居中) === */
#b_header {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 80px !important;
background: transparent !important;
display: flex !important;
justify-content: center !important;
align-items: center !important;
z-index: 9999 !important;
backdrop-filter: blur(0px); /* 保持顶部通透 */
border-bottom: none !important;
}
/* 搜索表单美化 */
form#sb_form {
width: var(--CONTAINER_WIDTH) !important;
max-width: 90vw !important;
height: 50px !important;
background: rgba(255, 255, 255, 0.95) !important;
border: var(--glass-border) !important;
box-shadow: 0 4px 15px rgba(0,0,0,0.1) !important;
border-radius: 25px !important;
display: flex !important;
align-items: center !important;
padding: 0 15px !important;
margin: 0 !important;
position: relative !important;
top: 10px !important; /* 微调位置 */
}
/* 搜索框内元素调整 */
.b_searchboxForm { border: none !important; }
#sb_form_q {
margin: 0 !important;
padding: 0 10px !important;
font-size: 16px !important;
height: 100% !important;
line-height: 50px !important;
}
/* 隐藏多余按钮 */
#sb_form_go, #sb_search { display: none !important; }
.b_logoArea { margin-right: 10px !important; margin-bottom: 0 !important;}
/* === 内容区域 (关键修复:防止内容偏移) === */
#b_content {
display: flex !important;
justify-content: center !important;
padding-top: 120px !important; /* 避开顶部悬浮栏 */
padding-left: 0 !important;
padding-right: 0 !important;
margin: 0 !important;
width: 100% !important;
background: transparent !important;
}
#b_results {
width: ${CONFIG.CONTAINER_WIDTH} !important;
max-width: 95vw !important;
margin: 0 !important;
padding: 0 !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
background: transparent !important;
}
/* === 结果卡片美化 === */
li.b_algo {
width: 100% !important;
background: var(--glass-card) !important;
backdrop-filter: blur(10px);
border-radius: 12px !important;
padding: 20px 25px !important;
margin-bottom: 20px !important;
box-shadow: var(--shadow-soft) !important;
border: var(--glass-border) !important;
transition: transform 0.2s, box-shadow 0.2s;
list-style: none !important;
box-sizing: border-box !important;
}
li.b_algo:hover {
transform: translateY(-2px);
box-shadow: 0 12px 40px rgba(0,0,0,0.12) !important;
background: rgba(255,255,255,0.98) !important;
}
/* 标题与文字优化 */
.b_algo h2 { margin-bottom: 8px !important; }
.b_algo h2 a {
color: #1a0dab !important;
font-size: 18px !important;
text-decoration: none !important;
font-weight: 600 !important;
}
.b_caption p {
color: var(--text-secondary) !important;
font-size: 14px !important;
line-height: 1.6 !important;
}
/* 链接绿色部分 */
.b_algo .b_attribution { border-top: none !important; }
/* 屏蔽按钮样式 */
.zen-block-btn {
float: right;
font-size: 12px;
color: #aaa;
cursor: pointer;
opacity: 0;
transition: opacity 0.2s;
padding: 2px 6px;
border: 1px solid #eee;
border-radius: 4px;
}
li.b_algo:hover .zen-block-btn { opacity: 1; }
.zen-block-btn:hover { background: #fee; color: red; border-color: red; }
/* === 设置弹窗样式 === */
#zen-settings {
position: fixed;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
width: 400px;
background: white;
padding: 30px;
border-radius: 16px;
box-shadow: 0 25px 50px rgba(0,0,0,0.3);
z-index: 100000;
display: none;
font-family: system-ui, -apple-system, sans-serif;
}
#zen-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.4); z-index: 99999; display: none;
backdrop-filter: blur(5px);
}
.zen-row { margin-bottom: 15px; }
.zen-label { display: block; margin-bottom: 5px; font-weight: bold; color: #333; }
.zen-input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 8px; box-sizing: border-box; }
.zen-btn { padding: 10px 20px; border-radius: 8px; border: none; cursor: pointer; font-weight: bold; }
.zen-save { background: #0078d4; color: white; float: right; }
.zen-cancel { background: #f3f3f3; color: #333; }
`;
GM_addStyle(css);
}
// ================= 逻辑处理 =================
class BingZenEngine {
constructor() {
this.blocklist = [];
this.init();
}
async init() {
// 加载数据
const savedBg = await GM_getValue(CONFIG.KEY_BG, CONFIG.DEFAULT_BG);
this.blocklist = JSON.parse(await GM_getValue(CONFIG.KEY_BLOCK, '[]'));
// 注入样式
injectStyles(savedBg);
// 注册菜单
GM_registerMenuCommand("⚙️ Zen 模式设置", () => this.toggleSettings(true));
// 构建 UI
this.buildSettingsUI();
// 启动 DOM 监控 (处理动态加载的内容和广告)
this.startObserver();
}
startObserver() {
const observer = new MutationObserver((mutations) => {
this.processNodes();
});
// 监控 body 的变化,应对 Bing 的 SPA 加载机制
observer.observe(document.body, { childList: true, subtree: true });
// 首次运行
setTimeout(() => this.processNodes(), 100);
window.onload = () => this.processNodes();
}
processNodes() {
// 1. 移除广告和无用元素 (更强力的选择器)
const trash = document.querySelectorAll('.b_ad, .b_adBottom, .b_algo.b_ad, #b_context, #b_pole, .sb_adsWv2');
trash.forEach(el => el.remove());
// 2. 处理结果卡片
const cards = document.querySelectorAll('li.b_algo');
cards.forEach(card => {
if (card.dataset.processed) return;
// 提取域名用于屏蔽功能
const link = card.querySelector('h2 a');
const url = link ? link.href : '';
const domain = this.extractDomain(url);
// 检查屏蔽列表
if (this.blocklist.some(blocked => domain.includes(blocked))) {
card.remove();
return;
}
// 添加屏蔽按钮
const titleArea = card.querySelector('h2');
if (titleArea) {
const btn = document.createElement('span');
btn.className = 'zen-block-btn';
btn.innerText = '🚫 屏蔽此站';
btn.onclick = (e) => {
e.preventDefault();
e.stopPropagation();
if (confirm(`确定要永久屏蔽来自 ${domain} 的搜索结果吗?`)) {
this.addToBlocklist(domain);
card.remove();
}
};
titleArea.prepend(btn);
}
card.dataset.processed = "true";
});
}
extractDomain(url) {
try {
return new URL(url).hostname;
} catch (e) {
return '';
}
}
async addToBlocklist(domain) {
if (!domain) return;
this.blocklist.push(domain);
await GM_setValue(CONFIG.KEY_BLOCK, JSON.stringify(this.blocklist));
}
buildSettingsUI() {
const overlay = document.createElement('div');
overlay.id = 'zen-overlay';
const modal = document.createElement('div');
modal.id = 'zen-settings';
modal.innerHTML = `
<h2 style="margin-top:0">Bing Zen 设置</h2>
<div class="zen-row">
<label class="zen-label">背景图片链接 (直链):</label>
<input class="zen-input" id="zen-bg-input" placeholder="https://...">
</div>
<div class="zen-row">
<label class="zen-label">屏蔽列表 (用逗号分隔):</label>
<textarea class="zen-input" id="zen-block-input" style="height:100px"></textarea>
</div>
<div style="margin-top:20px; overflow:hidden;">
<button class="zen-btn zen-cancel" id="zen-close-btn">取消</button>
<button class="zen-btn zen-save" id="zen-save-btn">保存并刷新</button>
</div>
`;
document.body.appendChild(overlay);
document.body.appendChild(modal);
// 绑定事件
document.getElementById('zen-close-btn').onclick = () => this.toggleSettings(false);
document.getElementById('zen-overlay').onclick = () => this.toggleSettings(false);
document.getElementById('zen-save-btn').onclick = async () => {
const bg = document.getElementById('zen-bg-input').value.trim();
const blockText = document.getElementById('zen-block-input').value;
const blockArr = blockText.split(/,|,|\n/).map(s => s.trim()).filter(s => s);
await GM_setValue(CONFIG.KEY_BG, bg || CONFIG.DEFAULT_BG);
await GM_setValue(CONFIG.KEY_BLOCK, JSON.stringify(blockArr));
location.reload();
};
}
async toggleSettings(show) {
const overlay = document.getElementById('zen-overlay');
const modal = document.getElementById('zen-settings');
if (show) {
const bg = await GM_getValue(CONFIG.KEY_BG, '');
document.getElementById('zen-bg-input').value = bg;
document.getElementById('zen-block-input').value = this.blocklist.join(', ');
overlay.style.display = 'block';
modal.style.display = 'block';
} else {
overlay.style.display = 'none';
modal.style.display = 'none';
}
}
}
// 启动引擎
new BingZenEngine();
})();