您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
美化必应搜索页面 (重构版 - 使用localStorage)
// ==UserScript== // @name 究极美化必应搜索页面(毛玻璃)(原生JS重构版) // @namespace http://tampermonkey.net/ // @version 3.0.3 // @description 美化必应搜索页面 (重构版 - 使用localStorage) // @author Onion (重构优化版) // @match *://*.cn.bing.com/* // @match *://*.bing.com/* // @match *://*.baidu.com/* // @icon https://gitee.com/onion-big/gitstore/raw/main/js/jpg/beautify.png // @license MPL2.0 // @grant GM_notification // @run-at document-start // ==/UserScript== (function() { 'use strict'; // ==================== 配置管理模块 ==================== class ConfigManager { constructor() { this.storageKey = 'bing_beautify_config'; this.cacheKey = 'bing_beautify_cache'; this.defaultConfig = { blurLevel: 13, opacity1: 83, // 渐变色透明度 (0-100) opacity2: 75, // 图片透明度 (0-100) backgroundType: 'gradient', // 'gradient' | 'image' | 'custom' backgroundImage: this.getDefaultImages()[0], customImageBase64: '', searchboxStyle: 'transparent' // 'transparent' | 'colorful' }; this.initConfig(); } getDefaultImages() { return [ "https://bing.biturl.top/?resolution=1920&format=image&index=0&mkt=zh-CN", "https://bing.com/th?id=OHR.NationalDay2022_ZH-CN3861603311_1920x1080.jpg", "https://bing.com/th?id=OHR.BridgeofSighs_ZH-CN5414607871_1920x1080.jpg", "https://images4.alphacoders.com/171/171916.jpg", "https://images5.alphacoders.com/613/613927.jpg", "https://images2.alphacoders.com/606/606275.jpg", "https://images2.alphacoders.com/742/742320.png", "https://dogefs.s3.ladydaily.com/~/source/wallhaven/full/8o/wallhaven-8o2dpj.png?w=2560&fmt=webp" ]; } initConfig() { try { const stored = localStorage.getItem(this.storageKey); this.config = stored ? { ...this.defaultConfig, ...JSON.parse(stored) } : { ...this.defaultConfig }; this.saveConfig(); } catch (error) { console.error('配置初始化失败:', error); this.config = { ...this.defaultConfig }; this.saveConfig(); } } get(key) { return this.config[key]; } set(key, value) { this.config[key] = value; this.saveConfig(); } update(updates) { Object.assign(this.config, updates); this.saveConfig(); } saveConfig() { try { localStorage.setItem(this.storageKey, JSON.stringify(this.config)); } catch (error) { console.error('配置保存失败:', error); } } reset() { this.config = { ...this.defaultConfig }; this.saveConfig(); } // 透明度转换:0-100 转为 0-255 的十六进制 opacityToHex(opacity) { const value = Math.round((opacity / 100) * 255); return value.toString(16).padStart(2, '0'); } // 十六进制转透明度:0-255 转为 0-100 hexToOpacity(hex) { if (!hex) return 80; const value = parseInt(hex, 16); return Math.round((value / 255) * 100); } // 图片缓存管理 getCachedImage(url) { try { const cache = JSON.parse(localStorage.getItem(this.cacheKey) || '{}'); const cached = cache[url]; // 必应每日壁纸需要每日更新 if (url.includes('bing.biturl.top') && cached) { const today = new Date().toDateString(); if (cached.date !== today) { delete cache[url]; localStorage.setItem(this.cacheKey, JSON.stringify(cache)); return null; } } return cached?.data || null; } catch (error) { console.error('获取缓存图片失败:', error); return null; } } setCachedImage(url, base64Data) { try { const cache = JSON.parse(localStorage.getItem(this.cacheKey) || '{}'); cache[url] = { data: base64Data, date: new Date().toDateString(), timestamp: Date.now() }; // 清理过期缓存(30天前) const expireTime = Date.now() - (30 * 24 * 60 * 60 * 1000); Object.keys(cache).forEach(key => { if (cache[key].timestamp < expireTime) { delete cache[key]; } }); localStorage.setItem(this.cacheKey, JSON.stringify(cache)); } catch (error) { console.error('缓存图片失败:', error); } } // 将图片转换为base64存储 async convertImageToBase64(imageUrl) { try { // 先检查缓存 const cached = this.getCachedImage(imageUrl); if (cached) { console.log('使用缓存图片:', imageUrl); return cached; } console.log('下载并缓存图片:', imageUrl); const response = await fetch(imageUrl); const blob = await response.blob(); return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onloadend = () => { const result = reader.result; // 缓存图片 this.setCachedImage(imageUrl, result); resolve(result); }; reader.onerror = reject; reader.readAsDataURL(blob); }); } catch (error) { console.error('图片转换base64失败:', error); return null; } } } // ==================== 样式管理模块 ==================== class StyleManager { constructor(config) { this.config = config; this.injectedStyles = new Set(); } injectGlobalStyles() { const css = ` @keyframes fadeIn { 0% { opacity: 0; transform: translateY(-10px); } 100% { opacity: 1; transform: translateY(0); } } /* 设置框样式 - 强制最高优先级 */ .beautify-settings { position: fixed !important; top: 50% !important; left: 50% !important; transform: translate(-50%, -50%) !important; width: min(520px, 95vw) !important; max-height: 85vh !important; background: rgba(255, 255, 255, 0.98) !important; backdrop-filter: blur(20px) !important; border-radius: 15px !important; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3) !important; z-index: 999999999 !important; padding: 0 !important; margin: 0 !important; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important; display: none !important; animation: fadeIn 0.3s ease-out !important; border: 2px solid rgba(76, 175, 80, 0.3) !important; overflow: hidden !important; pointer-events: auto !important; } .beautify-settings.show { display: block !important; visibility: visible !important; opacity: 1 !important; } .beautify-settings-header { display: flex !important; justify-content: space-between !important; align-items: center !important; padding: 15px 20px !important; border-bottom: 1px solid rgba(0, 0, 0, 0.1) !important; cursor: move !important; background: rgba(76, 175, 80, 0.1) !important; border-radius: 15px 15px 0 0 !important; flex-shrink: 0 !important; } .beautify-settings-title { font-size: 16px !important; font-weight: 600 !important; color: #333 !important; margin: 0 !important; white-space: nowrap !important; } .beautify-close-btn { background: rgba(255, 0, 0, 0.1) !important; border: none !important; font-size: 20px !important; cursor: pointer !important; color: #666 !important; padding: 5px !important; width: 30px !important; height: 30px !important; display: flex !important; align-items: center !important; justify-content: center !important; border-radius: 50% !important; transition: all 0.2s ease !important; flex-shrink: 0 !important; } .beautify-close-btn:hover { background: rgba(255, 0, 0, 0.2) !important; color: #ff0000 !important; transform: scale(1.1) !important; } .beautify-settings-content { padding: 20px !important; max-height: calc(85vh - 120px) !important; overflow-y: auto !important; background: rgba(255, 255, 255, 0.95) !important; border-radius: 0 0 15px 15px !important; } .beautify-form-group { margin-bottom: 18px !important; } .beautify-form-group:last-child { margin-bottom: 0 !important; } .beautify-label { display: block !important; margin-bottom: 8px !important; font-size: 14px !important; font-weight: 500 !important; color: #555 !important; white-space: nowrap !important; overflow: hidden !important; text-overflow: ellipsis !important; } .beautify-input, .beautify-select { width: 100% !important; padding: 10px 12px !important; border: 2px solid rgba(0, 0, 0, 0.1) !important; border-radius: 8px !important; font-size: 14px !important; background: white !important; transition: border-color 0.2s ease !important; box-sizing: border-box !important; } .beautify-input:focus, .beautify-select:focus { outline: none !important; border-color: #4CAF50 !important; } /* 滑块样式 */ .beautify-slider-container { display: flex !important; align-items: center !important; gap: 10px !important; } .beautify-slider { flex: 1 !important; height: 6px !important; background: #ddd !important; border-radius: 3px !important; outline: none !important; border: none !important; } .beautify-slider::-webkit-slider-thumb { appearance: none !important; width: 18px !important; height: 18px !important; background: #4CAF50 !important; border-radius: 50% !important; cursor: pointer !important; } .beautify-slider::-moz-range-thumb { width: 18px !important; height: 18px !important; background: #4CAF50 !important; border-radius: 50% !important; cursor: pointer !important; border: none !important; } .beautify-value-display { min-width: 45px !important; text-align: right !important; font-size: 12px !important; color: #666 !important; background: rgba(0, 0, 0, 0.05) !important; padding: 4px 8px !important; border-radius: 4px !important; } .beautify-button-group { display: flex !important; gap: 10px !important; margin-top: 20px !important; padding-top: 15px !important; border-top: 1px solid rgba(0, 0, 0, 0.1) !important; } .beautify-btn { flex: 1 !important; padding: 10px 16px !important; border: none !important; border-radius: 8px !important; font-size: 13px !important; font-weight: 500 !important; cursor: pointer !important; transition: all 0.2s ease !important; } .beautify-btn-primary { background: #4CAF50 !important; color: white !important; } .beautify-btn-primary:hover { background: #45a049 !important; transform: translateY(-1px) !important; } .beautify-btn-secondary { background: #f5f5f5 !important; color: #666 !important; } .beautify-btn-secondary:hover { background: #e5e5e5 !important; transform: translateY(-1px) !important; } /* 搜索框控制按钮 */ .beautify-control-buttons { display: flex !important; gap: 5px !important; } .beautify-control-btn { padding: 8px 12px !important; background: rgba(255, 255, 255, 0.9) !important; border: 1px solid rgba(0, 0, 0, 0.1) !important; border-radius: 6px !important; font-size: 12px !important; cursor: pointer !important; transition: all 0.2s ease !important; color: #444 !important; backdrop-filter: blur(10px) !important; } .beautify-control-btn:hover { background: rgba(255, 255, 255, 1) !important; transform: translateY(-1px) !important; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1) !important; } .beautify-control-btn.active { background: #4CAF50 !important; color: white !important; } /* 透明化处理 */ .pagereco_CB, .pagereco_CBImageCard, .pagereco_CBTextCard, #tabcontrol_8_156412_navr, #lMapContainer, .b_algoSlug .algoSlug_icon, #b_PagAboveFooter, .tta_incell, .tta_outcell, #tta_output_ta { background: transparent !important; border: none !important; } /* Header 统一背景 */ #b_header { border-bottom: none !important; background: transparent !important; } .b_searchboxForm { background: rgba(255, 255, 255, 0.8) !important; backdrop-filter: blur(10px) !important; border-radius: 25px !important; } /* 结果框样式 */ .b_algo, .b_ans { border-radius: 10px !important; backdrop-filter: blur(${this.config.get('blurLevel')}px) !important; margin-bottom: 15px !important; transition: all 0.3s ease !important; } .b_algo:hover, .b_ans:hover { transform: translateY(-2px) !important; box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1) !important; } /* 文件上传样式 */ .beautify-file-upload { position: relative !important; display: inline-block !important; width: 100% !important; } .beautify-file-input { position: absolute !important; opacity: 0 !important; width: 100% !important; height: 100% !important; cursor: pointer !important; } .beautify-file-label { display: block !important; padding: 12px 15px !important; border: 2px dashed rgba(0, 0, 0, 0.2) !important; border-radius: 8px !important; text-align: center !important; cursor: pointer !important; transition: all 0.2s ease !important; background: rgba(0, 0, 0, 0.02) !important; font-size: 13px !important; } .beautify-file-label:hover { border-color: #4CAF50 !important; background: rgba(76, 175, 80, 0.05) !important; } /* 遮罩层 */ .beautify-overlay { position: fixed !important; top: 0 !important; left: 0 !important; width: 100vw !important; height: 100vh !important; background: rgba(0, 0, 0, 0.3) !important; z-index: 999999998 !important; display: none !important; } .beautify-overlay.show { display: block !important; } `; this.injectCSS('global-styles', css); } injectCSS(id, css) { if (this.injectedStyles.has(id)) return; const style = document.createElement('style'); style.id = id; style.textContent = css; (document.head || document.documentElement).appendChild(style); this.injectedStyles.add(id); } updateResultBoxStyles() { const opacity1 = this.config.get('opacity1'); const opacity2 = this.config.get('opacity2'); const opacity = this.config.get('backgroundType') === 'image' ? opacity2 : opacity1; const alpha = opacity / 100; const elements = document.querySelectorAll('.b_algo, .b_ans'); elements.forEach(el => { el.style.backgroundColor = `rgba(255, 255, 255, ${alpha})`; el.style.backdropFilter = `blur(${this.config.get('blurLevel')}px)`; }); } updateSearchboxStyle() { const searchboxForm = document.querySelector('.b_searchboxForm'); if (!searchboxForm) return; const style = this.config.get('searchboxStyle'); const opacity2 = this.config.get('opacity2') / 100; if (style === 'transparent') { searchboxForm.style.background = `rgba(255, 255, 255, ${opacity2})`; searchboxForm.style.backgroundImage = 'none'; } else if (style === 'colorful') { searchboxForm.style.backgroundImage = 'linear-gradient(to right, rgb(255, 221, 238), skyblue)'; searchboxForm.style.background = 'none'; } } async updateHeaderBackground() { // 统一header背景 const header = document.getElementById('b_header'); if (!header) return; const backgroundType = this.config.get('backgroundType'); let backgroundImage = ''; switch (backgroundType) { case 'gradient': backgroundImage = 'linear-gradient(to right, #FFDDEE, skyblue)'; break; case 'image': const imageUrl = this.config.get('backgroundImage'); const cachedImage = await this.config.convertImageToBase64(imageUrl); backgroundImage = `url(${cachedImage || imageUrl})`; break; case 'custom': const base64Image = this.config.get('customImageBase64'); if (base64Image) { backgroundImage = `url(${base64Image})`; } else { backgroundImage = 'linear-gradient(to right, #FFDDEE, skyblue)'; } break; } header.style.background = backgroundImage; header.style.backgroundSize = 'cover'; header.style.backgroundPosition = 'center'; header.style.backgroundAttachment = 'fixed'; } } // ==================== 背景管理模块 ==================== class BackgroundManager { constructor(config) { this.config = config; } async applyBackground() { const container = document.getElementById('b_content') || document.documentElement; const backgroundType = this.config.get('backgroundType'); // 清除之前的背景设置 container.style.backgroundImage = ''; container.style.backgroundColor = ''; document.documentElement.style.background = ''; switch (backgroundType) { case 'gradient': this.applyGradientBackground(container); break; case 'image': await this.applyImageBackground(container); break; case 'custom': this.applyCustomBackground(container); break; } } applyGradientBackground(container) { container.style.backgroundImage = 'linear-gradient(to right, #FFDDEE, skyblue)'; container.style.backgroundAttachment = 'fixed'; } async applyImageBackground(container) { const imageUrl = this.config.get('backgroundImage'); // 尝试使用缓存的base64图片 const cachedImage = await this.config.convertImageToBase64(imageUrl); if (cachedImage) { container.style.background = `url(${cachedImage}) center/cover fixed`; } else { // 回退到直接URL container.style.background = `url(${imageUrl}) center/cover fixed`; } } applyCustomBackground(container) { const base64Image = this.config.get('customImageBase64'); if (base64Image) { container.style.background = `url(${base64Image}) center/cover fixed`; } else { this.applyGradientBackground(container); // 回退到渐变色 } } // 为百度设置特殊背景 applyBaiduBackground() { const wrapper = document.getElementById('wrapper_wrapper'); if (wrapper) { const imageUrl = this.config.get('backgroundImage'); wrapper.style.background = `url(${imageUrl}) center/cover fixed`; } } } // ==================== UI管理模块 ==================== class UIManager { constructor(config, styleManager, backgroundManager) { this.config = config; this.styleManager = styleManager; this.backgroundManager = backgroundManager; this.settingsPanel = null; this.overlay = null; this.dragData = { isDragging: false, offset: { x: 0, y: 0 } }; } createControlButtons() { const scopebar = document.querySelector('.b_scopebar'); if (!scopebar || !scopebar.children[0]) return; const controlContainer = document.createElement('div'); controlContainer.className = 'beautify-control-buttons'; const buttons = [ { text: '透明', action: () => this.setSearchboxStyle('transparent') }, { text: '炫彩', action: () => this.setSearchboxStyle('colorful') }, { text: '渐变', action: () => this.setBackgroundType('gradient') }, { text: '图片', action: () => this.setBackgroundType('image') } ]; buttons.forEach(btn => { const button = document.createElement('button'); button.className = 'beautify-control-btn'; button.textContent = btn.text; button.addEventListener('click', btn.action); controlContainer.appendChild(button); }); // 设置按钮 const settingsBtn = document.createElement('button'); settingsBtn.className = 'beautify-control-btn'; settingsBtn.textContent = '⚙️'; settingsBtn.style.fontSize = '16px'; settingsBtn.addEventListener('click', () => { console.log('设置按钮被点击了'); this.showSettingsPanel(); }); const headerNav = document.getElementById('id_h'); if (headerNav) { headerNav.appendChild(settingsBtn); } else { // 如果找不到id_h,就添加到控制按钮组里 controlContainer.appendChild(settingsBtn); } scopebar.children[0].appendChild(controlContainer); } async setSearchboxStyle(style) { this.config.set('searchboxStyle', style); this.styleManager.updateSearchboxStyle(); this.updateActiveButtons(); } async setBackgroundType(type) { this.config.set('backgroundType', type); await this.backgroundManager.applyBackground(); await this.styleManager.updateHeaderBackground(); this.styleManager.updateResultBoxStyles(); this.updateActiveButtons(); } updateActiveButtons() { // 更新按钮激活状态 document.querySelectorAll('.beautify-control-btn').forEach(btn => { btn.classList.remove('active'); }); const searchboxStyle = this.config.get('searchboxStyle'); const backgroundType = this.config.get('backgroundType'); document.querySelectorAll('.beautify-control-btn').forEach(btn => { if ((btn.textContent === '透明' && searchboxStyle === 'transparent') || (btn.textContent === '炫彩' && searchboxStyle === 'colorful') || (btn.textContent === '渐变' && backgroundType === 'gradient') || (btn.textContent === '图片' && backgroundType === 'image')) { btn.classList.add('active'); } }); } createOverlay() { if (this.overlay) return; this.overlay = document.createElement('div'); this.overlay.className = 'beautify-overlay'; this.overlay.addEventListener('click', () => this.hideSettingsPanel()); document.body.appendChild(this.overlay); } createSettingsPanel() { console.log('创建设置面板'); if (this.settingsPanel) { console.log('设置面板已存在'); return; } // 创建遮罩层 this.createOverlay(); const panel = document.createElement('div'); panel.className = 'beautify-settings'; panel.innerHTML = ` <div class="beautify-settings-header"> <h3 class="beautify-settings-title">🎨 美化设置</h3> <button class="beautify-close-btn" type="button">×</button> </div> <div class="beautify-settings-content"> <div class="beautify-form-group"> <label class="beautify-label">模糊度 (0-100)</label> <div class="beautify-slider-container"> <input type="range" class="beautify-input beautify-slider" id="blur-slider" min="0" max="100" value="${this.config.get('blurLevel')}"> <span class="beautify-value-display" id="blur-value">${this.config.get('blurLevel')}px</span> </div> </div> <div class="beautify-form-group"> <label class="beautify-label">渐变色透明度 (0-100)</label> <div class="beautify-slider-container"> <input type="range" class="beautify-input beautify-slider" id="opacity1-slider" min="0" max="100" value="${this.config.get('opacity1')}"> <span class="beautify-value-display" id="opacity1-value">${this.config.get('opacity1')}%</span> </div> </div> <div class="beautify-form-group"> <label class="beautify-label">图片背景透明度 (0-100)</label> <div class="beautify-slider-container"> <input type="range" class="beautify-input beautify-slider" id="opacity2-slider" min="0" max="100" value="${this.config.get('opacity2')}"> <span class="beautify-value-display" id="opacity2-value">${this.config.get('opacity2')}%</span> </div> </div> <div class="beautify-form-group"> <label class="beautify-label">背景类型</label> <select class="beautify-select" id="background-type"> <option value="gradient" ${this.config.get('backgroundType') === 'gradient' ? 'selected' : ''}>渐变色</option> <option value="image" ${this.config.get('backgroundType') === 'image' ? 'selected' : ''}>预设图片</option> <option value="custom" ${this.config.get('backgroundType') === 'custom' ? 'selected' : ''}>自定义图片</option> </select> </div> <div class="beautify-form-group"> <label class="beautify-label">预设图片</label> <select class="beautify-select" id="background-image"> ${this.createImageOptions()} </select> </div> <div class="beautify-form-group"> <label class="beautify-label">上传自定义图片</label> <div class="beautify-file-upload"> <input type="file" class="beautify-file-input" id="custom-image" accept="image/*"> <label for="custom-image" class="beautify-file-label"> 📷 点击选择图片文件 </label> </div> </div> <div class="beautify-button-group"> <button class="beautify-btn beautify-btn-secondary" id="reset-btn">🔄 重置</button> <button class="beautify-btn beautify-btn-primary" id="save-btn">💾 保存</button> </div> </div> `; document.body.appendChild(panel); this.settingsPanel = panel; console.log('设置面板已添加到DOM'); this.setupPanelEvents(); } createImageOptions() { const images = this.config.getDefaultImages(); return images.map((url, index) => { const selected = url === this.config.get('backgroundImage') ? 'selected' : ''; const label = index === 0 ? '必应每日壁纸' : `预设图片 ${index}`; return `<option value="${url}" ${selected}>${label}</option>`; }).join(''); } setupPanelEvents() { const panel = this.settingsPanel; // 关闭按钮 panel.querySelector('.beautify-close-btn').addEventListener('click', () => { this.hideSettingsPanel(); }); // 拖拽功能 const header = panel.querySelector('.beautify-settings-header'); this.setupDragEvents(header, panel); // 模糊度滑块 const blurSlider = panel.querySelector('#blur-slider'); const blurValue = panel.querySelector('#blur-value'); blurSlider.addEventListener('input', (e) => { const value = e.target.value; blurValue.textContent = `${value}px`; }); // 透明度1滑块 const opacity1Slider = panel.querySelector('#opacity1-slider'); const opacity1Value = panel.querySelector('#opacity1-value'); opacity1Slider.addEventListener('input', (e) => { const value = e.target.value; opacity1Value.textContent = `${value}%`; }); // 透明度2滑块 const opacity2Slider = panel.querySelector('#opacity2-slider'); const opacity2Value = panel.querySelector('#opacity2-value'); opacity2Slider.addEventListener('input', (e) => { const value = e.target.value; opacity2Value.textContent = `${value}%`; }); // 自定义图片上传 panel.querySelector('#custom-image').addEventListener('change', (e) => { this.handleImageUpload(e.target.files[0]); }); // 保存按钮 panel.querySelector('#save-btn').addEventListener('click', () => { this.saveSettings(); }); // 重置按钮 panel.querySelector('#reset-btn').addEventListener('click', () => { this.resetSettings(); }); } setupDragEvents(handle, element) { handle.addEventListener('mousedown', (e) => { this.dragData.isDragging = true; this.dragData.offset.x = e.clientX - element.offsetLeft; this.dragData.offset.y = e.clientY - element.offsetTop; handle.style.cursor = 'grabbing'; }); document.addEventListener('mousemove', (e) => { if (!this.dragData.isDragging) return; const x = e.clientX - this.dragData.offset.x; const y = e.clientY - this.dragData.offset.y; element.style.left = `${x}px`; element.style.top = `${y}px`; element.style.transform = 'none'; }); document.addEventListener('mouseup', () => { this.dragData.isDragging = false; handle.style.cursor = 'move'; }); } async handleImageUpload(file) { if (!file) return; try { const base64 = await this.fileToBase64(file); this.config.set('customImageBase64', base64); GM_notification({ text: '图片上传成功!', timeout: 2000 }); } catch (error) { console.error('图片上传失败:', error); GM_notification({ text: '图片上传失败,请重试', timeout: 3000 }); } } fileToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); reader.onerror = reject; reader.readAsDataURL(file); }); } async saveSettings() { const panel = this.settingsPanel; const updates = { blurLevel: parseInt(panel.querySelector('#blur-slider').value), opacity1: parseInt(panel.querySelector('#opacity1-slider').value), opacity2: parseInt(panel.querySelector('#opacity2-slider').value), backgroundType: panel.querySelector('#background-type').value, backgroundImage: panel.querySelector('#background-image').value }; this.config.update(updates); await this.backgroundManager.applyBackground(); await this.styleManager.updateHeaderBackground(); this.styleManager.updateResultBoxStyles(); this.styleManager.updateSearchboxStyle(); this.updateActiveButtons(); GM_notification({ text: '设置已保存!', timeout: 2000 }); this.hideSettingsPanel(); } async resetSettings() { this.config.reset(); await this.backgroundManager.applyBackground(); await this.styleManager.updateHeaderBackground(); this.styleManager.updateResultBoxStyles(); this.styleManager.updateSearchboxStyle(); this.updateActiveButtons(); GM_notification({ text: '设置已重置为默认值!', timeout: 2000 }); this.hideSettingsPanel(); } showSettingsPanel() { console.log('显示设置面板'); if (!this.settingsPanel) { this.createSettingsPanel(); } // 强制显示 this.overlay.classList.add('show'); this.settingsPanel.classList.add('show'); this.settingsPanel.style.display = 'block'; this.settingsPanel.style.visibility = 'visible'; this.settingsPanel.style.opacity = '1'; this.settingsPanel.style.zIndex = '999999999'; console.log('设置面板显示状态:', this.settingsPanel.style.display); } hideSettingsPanel() { if (this.settingsPanel) { this.settingsPanel.classList.remove('show'); this.settingsPanel.style.display = 'none'; } if (this.overlay) { this.overlay.classList.remove('show'); } } } // ==================== 增强功能模块 ==================== class EnhancementManager { constructor(config) { this.config = config; } enhanceSearchBox() { const searchBox = document.querySelector('.b_searchbox'); if (!searchBox) return; // 搜索框获得焦点时扩展宽度 searchBox.addEventListener('focus', () => { searchBox.style.transition = 'all 0.3s ease'; searchBox.style.width = '600px'; }); // 点击页面其他地方时恢复宽度 document.addEventListener('click', (e) => { if (!e.target.closest('.b_searchboxForm')) { searchBox.style.width = ''; } }); } enhanceResults() { // 结果框悬停效果已在CSS中处理 this.fixResultOverflow(); this.cleanupFooter(); } fixResultOverflow() { // 修复相关搜索框宽度 const relatedBox = document.querySelector('.b_rrsr .b_vlist2col'); if (relatedBox?.children[0]?.children[1]) { Array.from(relatedBox.children[0].children[1].children) .forEach(item => item.style.width = '45%'); } // 修复其他溢出问题 const brsv3 = document.getElementById('brsv3'); if (brsv3?.children[1]) { Array.from(brsv3.children[1].children) .forEach(item => item.style.width = '45%'); } } cleanupFooter() { const footer = document.getElementById('b_footer'); if (footer) { footer.style.background = 'rgba(0, 0, 0, 0.8)'; footer.style.backdropFilter = 'blur(10px)'; } const mfaSrch = document.getElementById('mfa_srch'); if (mfaSrch) { mfaSrch.style.backdropFilter = 'blur(10px)'; mfaSrch.style.background = 'transparent'; } } setupKeyboardShortcuts() { document.addEventListener('keydown', (e) => { // Ctrl + / 打开设置 if (e.ctrlKey && e.code === 'Slash') { e.preventDefault(); const settingsBtn = document.querySelector('.beautify-control-btn[textContent="⚙️"]'); if (settingsBtn) settingsBtn.click(); } }); } cleanupOtherElements() { // 清理其他元素的背景 const selectors = [ '.qna_algo', '.slide', '.nws_cwrp', '.mc_vhvc_th', '.na_ccw' ]; selectors.forEach(selector => { document.querySelectorAll(selector).forEach(el => { el.style.background = 'transparent'; if (el.children[0]) { el.children[0].style.background = 'transparent'; } }); }); } } // ==================== 主应用类 ==================== class BingBeautifier { constructor() { this.config = new ConfigManager(); this.styleManager = new StyleManager(this.config); this.backgroundManager = new BackgroundManager(this.config); this.uiManager = new UIManager(this.config, this.styleManager, this.backgroundManager); this.enhancementManager = new EnhancementManager(this.config); } init() { console.log('初始化美化脚本'); // 根据不同域名执行不同逻辑 if (this.isBingSearch()) { this.initBing(); } else if (this.isBaidu()) { this.initBaidu(); } } isBingSearch() { return window.location.href.includes('bing.com/search'); } isBaidu() { return window.location.href.includes('baidu.com'); } async initBing() { console.log('初始化必应美化'); // 立即注入基础样式 this.styleManager.injectGlobalStyles(); // 使用async/await优化异步操作 const initializeUI = async () => { // 应用背景 await this.backgroundManager.applyBackground(); // 更新header背景 await this.styleManager.updateHeaderBackground(); // 更新样式 this.styleManager.updateResultBoxStyles(); this.styleManager.updateSearchboxStyle(); // 增强功能 this.enhancementManager.enhanceSearchBox(); this.enhancementManager.enhanceResults(); this.enhancementManager.setupKeyboardShortcuts(); this.enhancementManager.cleanupOtherElements(); }; // 检查DOM是否准备好 const checkAndInit = async () => { const scopebar = document.querySelector('.b_scopebar'); if (scopebar) { // 创建UI控件 this.uiManager.createControlButtons(); this.uiManager.updateActiveButtons(); await initializeUI(); console.log('必应搜索美化已应用'); } else { // 如果DOM还没准备好,稍后再试 setTimeout(checkAndInit, 100); } }; // 立即执行基础初始化 await initializeUI(); // 检查并创建UI控件 checkAndInit(); } initBaidu() { // 简单的百度页面美化 this.backgroundManager.applyBaiduBackground(); console.log('百度页面美化已应用'); } } // ==================== 初始化 ==================== function main() { try { const beautifier = new BingBeautifier(); beautifier.init(); } catch (error) { console.error('美化脚本初始化失败:', error); } } // 等待DOM加载完成 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', main); } else { main(); } // 错误处理 window.addEventListener('error', (e) => { console.error('脚本运行时错误:', e.error); }, true); })();