Bing Zen Mode (2025 Evolution) - 极致美化/修复内容消失

极致纯净的 Bing 搜索体验。修复内容消失问题,卡片式布局,强力去广告,自定义背景,完美居中。

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==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();

})();