Google搜索增强

采用Google原生风格在左侧显示中文语言过滤、时间过滤和文件类型过滤,优化显示条件

// ==UserScript==
// @name         Google搜索增强
// @namespace    http://tampermonkey.net/
// @version      6.3
// @description  采用Google原生风格在左侧显示中文语言过滤、时间过滤和文件类型过滤,优化显示条件
// @author       You
// @match        https://www.google.com/search*
// @match        https://www.google.com.hk/search*
// @match        https://www.google.cn/search*
// @grant        none
// @license MIT
// ==/UserScript==


(function() {
    'use strict';

    // 等待页面元素加载
    function waitForElement(selector, callback) {
        const element = document.querySelector(selector);
        if (element) {
            callback(element);
        } else {
            setTimeout(() => waitForElement(selector, callback), 100);
        }
    }

    // 生成过滤后的URL
    function generateFilterUrl(langFilter = null, timeFilter = null, fileFilter = null) {
        const currentUrl = new URL(window.location.href);
        const urlParams = currentUrl.searchParams;
        let query = urlParams.get('q') || '';

        if (langFilter !== null) {
            if (langFilter === 'all') {
                urlParams.delete('lr');
            } else {
                urlParams.set('lr', langFilter);
            }
        }

        if (timeFilter !== null) {
            if (timeFilter === 'all') {
                urlParams.delete('tbs');
            } else {
                urlParams.set('tbs', timeFilter);
            }
        }

        if (fileFilter !== null) {
            query = query.replace(/\s*filetype:\w+/g, '');

            if (fileFilter !== '' && fileFilter !== 'all') {
                query = (query.trim() + ' filetype:' + fileFilter).trim();
            }

            urlParams.set('q', query);
        }

        return currentUrl.toString();
    }

    // 生成高级搜索URL
    function generateAdvancedSearchUrl() {
        const urlParams = new URLSearchParams(window.location.search);
        const currentQuery = urlParams.get('q') || '';
        const currentHost = window.location.host;

        // 构建高级搜索URL,保持当前搜索词
        const advancedUrl = `https://${currentHost}/advanced_search`;
        const advancedParams = new URLSearchParams();

        if (currentQuery) {
            advancedParams.set('q', currentQuery);
        }

        return `${advancedUrl}?${advancedParams.toString()}`;
    }

    // 获取当前过滤状态
    function getCurrentStatus() {
        const urlParams = new URLSearchParams(window.location.search);
        const currentLang = urlParams.get('lr') || 'all';
        const currentTime = urlParams.get('tbs') || 'all';
        const query = urlParams.get('q') || '';
        const fileTypeMatch = query.match(/filetype:(\w+)/);
        const currentFileType = fileTypeMatch ? fileTypeMatch[1] : '';

        let normalizedLang = currentLang;
        if (currentLang.includes('lang_zh-CN|lang_zh-TW') || currentLang.includes('lang_zh-TW|lang_zh-CN')) {
            normalizedLang = 'lang_zh-CN|lang_zh-TW';
        }

        return { currentLang: normalizedLang, currentTime, currentFileType };
    }

    // 检查是否有足够空间显示
    function hasEnoughSpace() {
        return window.innerWidth >= 300;
    }

    // 创建纯原生风格左侧过滤器
    function createNativeLeftFilter() {
        const { currentLang, currentTime, currentFileType } = getCurrentStatus();

        const container = document.createElement('div');
        container.id = 'native-left-filter';
        container.style.cssText = `
            position: fixed;
            left: 20px;
            top: 160px;
            width: 150px;
            background: transparent;
            font-family: arial,sans-serif;
            font-size: 13px;
            color: #3c4043;
            z-index: 1000;
        `;

        const languageOptions = [
            { value: 'all', label: '全部结果', current: currentLang === 'all' },
            { value: 'lang_zh-CN|lang_zh-TW', label: '所有中文', current: currentLang === 'lang_zh-CN|lang_zh-TW' },
            { value: 'lang_zh-CN', label: '简体中文', current: currentLang === 'lang_zh-CN' },
            { value: 'lang_zh-TW', label: '繁体中文', current: currentLang === 'lang_zh-TW' }
        ];

        const timeOptions = [
            { value: 'all', label: '不限时间', current: currentTime === 'all' },
            { value: 'qdr:d', label: '一天内', current: currentTime.includes('qdr:d') },
            { value: 'qdr:w', label: '一周内', current: currentTime.includes('qdr:w') },
            { value: 'qdr:m', label: '一月内', current: currentTime.includes('qdr:m') && !currentTime.includes('qdr:m6') },
            { value: 'qdr:m6', label: '半年内', current: currentTime.includes('qdr:m6') },
            { value: 'qdr:y', label: '一年内', current: currentTime.includes('qdr:y') }
        ];

        function generateNativeSection(title, options, filterType) {
            const links = options.map(option => {
                const url = filterType === 'lang' ? generateFilterUrl(option.value, null, null) :
                           generateFilterUrl(null, option.value, null);

                const isActive = option.current;
                const style = isActive
                    ? 'color: #1a73e8; text-decoration: none; font-weight: 400; border-left: 3px solid #1a73e8; padding-left: 8px; background: #f8f9fa;'
                    : 'color: #5f6368; text-decoration: none; padding-left: 11px;';

                return `
                    <div style="margin-bottom: 1px;">
                        <a href="${url}" style="${style} display: block; padding-top: 4px; padding-bottom: 4px; padding-right: 8px; line-height: 18px;">
                            ${option.label}
                        </a>
                    </div>
                `;
            }).join('');

            return `
                <div style="margin-bottom: 24px;">
                    <div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
                        ${title}
                    </div>
                    ${links}
                </div>
            `;
        }

        // 文件类型清除链接
        const clearFileUrl = generateFilterUrl(null, null, '');
        const fileTypeSection = currentFileType ? `
            <div style="margin-bottom: 24px;">
                <div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
                    文件类型
                </div>
                <div style="margin-bottom: 1px;">
                    <div style="color: #1a73e8; display: block; padding: 4px 8px 4px 11px; line-height: 18px; border-left: 3px solid #1a73e8; background: #f8f9fa;">
                        ${currentFileType.toUpperCase()} 文件
                    </div>
                </div>
                <div style="margin-bottom: 1px;">
                    <a href="${clearFileUrl}" style="color: #5f6368; text-decoration: none; display: block; padding: 4px 8px 4px 11px; line-height: 18px;">
                        所有文件类型
                    </a>
                </div>
            </div>
        ` : '';

        // 生成高级搜索URL
        const advancedSearchUrl = generateAdvancedSearchUrl();

        container.innerHTML = `
            <style>
                #native-left-filter a:hover {
                    color: #1a73e8 !important;
                    text-decoration: underline;
                }

                #native-left-filter .file-input {
                    width: 100%;
                    border: none;
                    border-bottom: 1px solid #dadce0;
                    padding: 6px 0;
                    font-size: 14px;
                    outline: none;
                    background: transparent;
                    color: #3c4043;
                    margin-left: 11px;
                    box-sizing: border-box;
                    width: calc(100% - 11px);
                }

                #native-left-filter .file-input:focus {
                    border-bottom: 2px solid #1a73e8;
                }

                #native-left-filter .file-input::placeholder {
                    color: #5f6368;
                }

                #native-left-filter .advanced-search-link {
                    color: #1a73e8;
                    text-decoration: none;
                    display: block;
                    padding: 4px 8px 4px 11px;
                    line-height: 18px;
                    font-size: 13px;
                    border-left: 3px solid transparent;
                    transition: all 0.2s ease;
                }

                #native-left-filter .advanced-search-link:hover {
                    border-left: 3px solid #1a73e8;
                    background: #f8f9fa;
                    text-decoration: underline;
                }
            </style>

            ${generateNativeSection('语言', languageOptions, 'lang')}
            ${generateNativeSection('时间', timeOptions, 'time')}
            ${fileTypeSection}

            <div style="margin-bottom: 20px;">
                <div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
                    ${currentFileType ? '搜索其他文件' : '文件类型'}
                </div>
                <input type="text" class="file-input" id="file-ext-input" placeholder="按回车搜索" value="">
                <div style="font-size: 11px; color: #5f6368; margin-top: 6px; padding-left: 11px; line-height: 1.4;">
                    例如:pdf, doc
                </div>
            </div>

            <div style="margin-bottom: 16px;">
                <div style="color: #3c4043; font-size: 14px; font-weight: 400; margin-bottom: 8px; padding-left: 11px;">
                    更多选项
                </div>
                <div style="margin-bottom: 1px;">
                    <a href="${advancedSearchUrl}" target="_blank" class="advanced-search-link">
                        🔧 高级搜索
                    </a>
                </div>
            </div>
        `;

        return container;
    }

    // 设置事件处理器
    function setupEventHandlers(container) {
        const fileInput = container.querySelector('#file-ext-input');

        if (fileInput) {
            fileInput.addEventListener('keypress', (e) => {
                if (e.key === 'Enter') {
                    const fileType = fileInput.value.trim();
                    const url = generateFilterUrl(null, null, fileType);
                    window.location.href = url;
                }
            });

            // 输入框失去焦点时也可以搜索
            fileInput.addEventListener('blur', (e) => {
                const fileType = fileInput.value.trim();
                if (fileType && fileType !== getCurrentStatus().currentFileType) {
                    setTimeout(() => {
                        const url = generateFilterUrl(null, null, fileType);
                        window.location.href = url;
                    }, 200);
                }
            });
        }
    }

    // 初始化过滤器
    function initializeFilter() {
        // 移除现有元素
        const existingFilter = document.getElementById('native-left-filter');
        if (existingFilter) existingFilter.remove();

        // 检查是否有足够空间显示
        if (!hasEnoughSpace()) {
            return;
        }

        // 创建并添加过滤器
        const filter = createNativeLeftFilter();
        setupEventHandlers(filter);
        document.body.appendChild(filter);
    }

    // 主函数
    function main() {
        if (!window.location.pathname.includes('/search')) {
            return;
        }

        waitForElement('#search, #center_col, #main', () => {
            setTimeout(initializeFilter, 500);
        });

        // 监听窗口大小变化
        window.addEventListener('resize', () => {
            setTimeout(initializeFilter, 100);
        });
    }

    // 页面加载时执行
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', main);
    } else {
        main();
    }

    // 监听页面导航变化
    let currentUrl = location.href;
    const observer = new MutationObserver(() => {
        if (location.href !== currentUrl) {
            currentUrl = location.href;
            setTimeout(main, 500);
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址