<!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>快捷网址搜索</title> <style> html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; background: transparent; font-family: "Microsoft YaHei", "PingFang SC", "Segoe UI", sans-serif; user-select: none; -webkit-user-select: none; }
* { box-sizing: border-box; }
.card { width: 100%; height: 100%; border-radius: 18px; background: linear-gradient(145deg, #2b2d36 0%, #1c1d22 100%); border: 1px solid rgba(132, 146, 166, 0.15); box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.08), 0 8px 24px rgba(0, 0, 0, 0.5); display: flex; flex-direction: column; position: relative; color: #e4e7ed; }
.header { padding: 16px 20px 8px; display: flex; align-items: center; cursor: grab; font-size: 14px; font-weight: bold; color: rgba(255, 255, 255, 0.8); letter-spacing: 0.5px; } .header:active { cursor: grabbing; }
.header-icon { width: 16px; height: 16px; margin-right: 8px; fill: currentColor; opacity: 0.8; }
.main-content { flex: 1; display: flex; flex-direction: column; padding: 0 20px; justify-content: center; overflow: hidden; }
.engine-tabs { display: flex; gap: 10px; margin-bottom: 18px; overflow-x: auto; padding-bottom: 6px; }
.engine-tabs::-webkit-scrollbar { height: 4px; } .engine-tabs::-webkit-scrollbar-track { background: transparent; } .engine-tabs::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.1); border-radius: 4px; } .engine-tabs::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.2); }
.engine-tab { padding: 6px 16px; font-size: 13px; border-radius: 20px; background: rgba(255, 255, 255, 0.05); color: rgba(255, 255, 255, 0.6); cursor: pointer; transition: all 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94); border: 1px solid rgba(255, 255, 255, 0.03); white-space: nowrap; }
.engine-tab:hover { background: rgba(255, 255, 255, 0.1); color: rgba(255, 255, 255, 0.95); }
.engine-tab:active { transform: scale(0.95); }
.engine-tab.active { background: rgba(82, 153, 255, 0.15); color: #7ab3ff; border-color: rgba(82, 153, 255, 0.3); box-shadow: 0 0 12px rgba(82, 153, 255, 0.1); font-weight: 600; }
.search-container { display: flex; align-items: center; background: rgba(0, 0, 0, 0.3); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 14px; padding: 6px 8px 6px 16px; transition: all 0.3s ease; box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.2); }
.search-container:focus-within { border-color: rgba(122, 179, 255, 0.6); background: rgba(0, 0, 0, 0.4); box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.3), 0 0 0 3px rgba(122, 179, 255, 0.15); }
.search-input { flex: 1; background: transparent; border: none; outline: none; color: #ffffff; font-size: 15px; font-family: inherit; padding: 8px 0; caret-color: #7ab3ff; user-select: auto; -webkit-user-select: auto; }
.search-input::placeholder { color: rgba(255, 255, 255, 0.25); }
.search-btn { background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 10px; width: 38px; height: 38px; display: flex; align-items: center; justify-content: center; cursor: pointer; color: rgba(255, 255, 255, 0.8); transition: all 0.2s ease; margin-left: 10px; }
.search-btn:hover { background: #5299ff; color: #ffffff; border-color: #5299ff; box-shadow: 0 4px 12px rgba(82, 153, 255, 0.4); }
.search-btn:active { transform: scale(0.92); }
.search-btn svg { width: 18px; height: 18px; fill: currentColor; transition: transform 0.2s; } .search-btn:hover svg { transform: scale(1.1); }
.resize-handle { position: absolute; right: 6px; bottom: 6px; width: 14px; height: 14px; cursor: nwse-resize; background: radial-gradient(circle at 60% 60%, rgba(255,255,255,0.2) 1.5px, transparent 1.5px); background-size: 4px 4px; border-bottom-right-radius: 12px; opacity: 0.4; transition: opacity 0.2s; } .resize-handle:hover { opacity: 1; } </style></head><body> <div class="card"> <div class="header yanm-drag" data-yanm-drag="true"> <svg class="header-icon" viewBox="0 0 24 24"> <path d="M15.5,14L20.5,19L19,20.5L14,15.5V14.71L13.73,14.43C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.43,13.73L14.71,14H15.5M9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14M12,20V22H2V20H12Z" /> </svg> 极速探索 </div> <div class="main-content"> <div class="engine-tabs" id="engineTabs"></div> <div class="search-container"> <input type="text" id="searchInput" class="search-input" placeholder="输入你想知道的一切..." autocomplete="off" spellcheck="false" /> <button id="searchBtn" class="search-btn" title="立即搜索"> <svg viewBox="0 0 24 24"> <path d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z" /> </svg> </button> </div> </div> <div class="resize-handle yanm-resize" data-yanm-resize="true"></div> </div>
<script> const engines = [ { id: 'bing', name: '必应', url: 'https://cn.bing.com/search?q=' }, { id: 'google', name: 'Google', url: 'https://www.google.com/search?q=' }, { id: 'baidu', name: '百度', url: 'https://www.baidu.com/s?wd=' }, { id: 'bilibili', name: 'B站', url: 'https://search.bilibili.com/all?keyword=' }, { id: 'github', name: 'GitHub', url: 'https://github.com/search?q=' }, { id: 'zhihu', name: '知乎', url: 'https://www.zhihu.com/search?type=content&q=' } ];
let state = { activeEngine: 'bing' };
const STATE_KEY = 'yanm_widget_engine_state'; const engineTabsEl = document.getElementById('engineTabs'); const searchInputEl = document.getElementById('searchInput'); const searchBtnEl = document.getElementById('searchBtn');
function renderTabs() { engineTabsEl.innerHTML = ''; engines.forEach(engine => { const tab = document.createElement('div'); tab.className = `engine-tab ${state.activeEngine === engine.id ? 'active' : ''}`; tab.innerText = engine.name; tab.onclick = () => { state.activeEngine = engine.id; renderTabs(); saveState(); searchInputEl.focus(); }; engineTabsEl.appendChild(tab); }); }
function doSearch() { const query = searchInputEl.value.trim(); if (!query) { searchInputEl.focus(); return; } const engine = engines.find(e => e.id === state.activeEngine) || engines[0]; const targetUrl = engine.url + encodeURIComponent(query); if (window.yanm) { window.yanm.invoke('url.open', { url: targetUrl, closeAfterOpen: true }).catch(err => { console.error('Yanm URL open failed:', err); }); } else { window.open(targetUrl, '_blank'); } searchInputEl.value = ''; }
searchBtnEl.onclick = doSearch; searchInputEl.onkeydown = (e) => { if (e.key === 'Enter') { e.preventDefault(); doSearch(); } };
function saveState() { const stateStr = JSON.stringify(state); localStorage.setItem(STATE_KEY, stateStr); if (window.yanm) { window.yanm.invoke('state.set', { key: STATE_KEY, value: stateStr }).catch(console.error); } }
function applyState(stateStr) { if (!stateStr) return; try { const parsed = JSON.parse(stateStr); if (parsed && parsed.activeEngine) { state.activeEngine = parsed.activeEngine; renderTabs(); } } catch (e) { console.error('Parse state error:', e); } }
function init() { renderTabs(); const localState = localStorage.getItem(STATE_KEY); if (localState) { applyState(localState); } setTimeout(() => { searchInputEl.focus(); }, 200);
let attempts = 0; const tryConnectHost = () => { if (window.yanm) { window.yanm.invoke('state.get', { key: STATE_KEY }) .then(res => { if (res) applyState(res); }) .catch(err => console.warn('Yanmu state.get failed:', err)); } else if (attempts < 50) { attempts++; setTimeout(tryConnectHost, 100); } }; tryConnectHost(); }
init(); </script></body></html>