feat(search): 集成多搜索引擎功能
添加Google、Bing、百度外部搜索引擎集成,支持用户通过搜索框右侧图标选择搜索引擎
This commit is contained in:
@@ -679,6 +679,68 @@ body .content.expanded {
|
|||||||
color: var(--error-color);
|
color: var(--error-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 搜索图标和搜索引擎切换图标位置调整 */
|
||||||
|
.search-box .search-icon {
|
||||||
|
right: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box .search-engine-toggle {
|
||||||
|
right: 3.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 搜索引擎下拉菜单 */
|
||||||
|
.search-engine-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 5px);
|
||||||
|
right: 1rem;
|
||||||
|
background-color: var(--sidebar-bg);
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 15px var(--shadow-color);
|
||||||
|
display: none;
|
||||||
|
z-index: 100;
|
||||||
|
padding: 0.5rem;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-engine-dropdown.active {
|
||||||
|
display: flex;
|
||||||
|
animation: fadeIn 0.2s ease-out forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-engine-option {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin: 0.3rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
background-color: var(--card-bg-gradient-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-engine-option:hover {
|
||||||
|
background-color: var(--card-bg-gradient-2);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 3px 8px var(--shadow-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-engine-option.active {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-engine-option i {
|
||||||
|
position: static;
|
||||||
|
transform: none;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
/* 页面容器 */
|
/* 页面容器 */
|
||||||
.page {
|
.page {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
148
src/script.js
148
src/script.js
@@ -8,6 +8,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let isLightTheme = false; // 主题状态
|
let isLightTheme = false; // 主题状态
|
||||||
let isSidebarCollapsed = false; // 侧边栏折叠状态
|
let isSidebarCollapsed = false; // 侧边栏折叠状态
|
||||||
let pages; // 页面元素的全局引用
|
let pages; // 页面元素的全局引用
|
||||||
|
let currentSearchEngine = 'local'; // 当前选择的搜索引擎
|
||||||
|
|
||||||
// 搜索索引,用于提高搜索效率
|
// 搜索索引,用于提高搜索效率
|
||||||
let searchIndex = {
|
let searchIndex = {
|
||||||
@@ -15,12 +16,41 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
items: []
|
items: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 搜索引擎配置
|
||||||
|
const searchEngines = {
|
||||||
|
local: {
|
||||||
|
name: '本地搜索',
|
||||||
|
icon: 'fas fa-search',
|
||||||
|
url: null // 本地搜索不需要URL
|
||||||
|
},
|
||||||
|
google: {
|
||||||
|
name: 'Google搜索',
|
||||||
|
icon: 'fab fa-google',
|
||||||
|
url: 'https://www.google.com/search?q='
|
||||||
|
},
|
||||||
|
bing: {
|
||||||
|
name: 'Bing搜索',
|
||||||
|
icon: 'fab fa-microsoft',
|
||||||
|
url: 'https://www.bing.com/search?q='
|
||||||
|
},
|
||||||
|
baidu: {
|
||||||
|
name: '百度搜索',
|
||||||
|
icon: 'fas fa-paw',
|
||||||
|
url: 'https://www.baidu.com/s?wd='
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 获取DOM元素 - 基本元素
|
// 获取DOM元素 - 基本元素
|
||||||
const searchInput = document.getElementById('search');
|
const searchInput = document.getElementById('search');
|
||||||
const searchBox = document.querySelector('.search-box');
|
const searchBox = document.querySelector('.search-box');
|
||||||
const searchResultsPage = document.getElementById('search-results');
|
const searchResultsPage = document.getElementById('search-results');
|
||||||
const searchSections = searchResultsPage.querySelectorAll('.search-section');
|
const searchSections = searchResultsPage.querySelectorAll('.search-section');
|
||||||
|
|
||||||
|
// 搜索引擎相关元素
|
||||||
|
const searchIcon = document.querySelector('.search-icon');
|
||||||
|
const searchEngineDropdown = document.querySelector('.search-engine-dropdown');
|
||||||
|
const searchEngineOptions = document.querySelectorAll('.search-engine-option');
|
||||||
|
|
||||||
// 移动端元素
|
// 移动端元素
|
||||||
const menuToggle = document.querySelector('.menu-toggle');
|
const menuToggle = document.querySelector('.menu-toggle');
|
||||||
const searchToggle = document.querySelector('.search-toggle');
|
const searchToggle = document.querySelector('.search-toggle');
|
||||||
@@ -578,16 +608,129 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const debouncedSearch = debounce(performSearch, 300);
|
const debouncedSearch = debounce(performSearch, 300);
|
||||||
|
|
||||||
searchInput.addEventListener('input', (e) => {
|
searchInput.addEventListener('input', (e) => {
|
||||||
|
// 只有在选择了本地搜索时,才在输入时实时显示本地搜索结果
|
||||||
|
if (currentSearchEngine === 'local') {
|
||||||
debouncedSearch(e.target.value);
|
debouncedSearch(e.target.value);
|
||||||
|
} else {
|
||||||
|
// 对于非本地搜索,重置之前的本地搜索结果(如果有)
|
||||||
|
if (isSearchActive) {
|
||||||
|
resetSearch();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 初始化搜索引擎设置
|
||||||
|
function initSearchEngine() {
|
||||||
|
// 从本地存储获取上次选择的搜索引擎
|
||||||
|
const savedEngine = localStorage.getItem('searchEngine');
|
||||||
|
if (savedEngine && searchEngines[savedEngine]) {
|
||||||
|
currentSearchEngine = savedEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置当前搜索引擎的激活状态及图标
|
||||||
|
updateSearchEngineUI();
|
||||||
|
|
||||||
|
// 初始化搜索引擎下拉菜单事件
|
||||||
|
searchIcon.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
searchEngineDropdown.classList.toggle('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击搜索引擎选项
|
||||||
|
searchEngineOptions.forEach(option => {
|
||||||
|
// 初始化激活状态
|
||||||
|
if (option.getAttribute('data-engine') === currentSearchEngine) {
|
||||||
|
option.classList.add('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
option.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// 获取选中的搜索引擎
|
||||||
|
const engine = option.getAttribute('data-engine');
|
||||||
|
|
||||||
|
// 更新当前搜索引擎
|
||||||
|
if (engine && searchEngines[engine]) {
|
||||||
|
// 如果搜索引擎变更,且之前有活跃的本地搜索结果,重置搜索状态
|
||||||
|
if (currentSearchEngine !== engine && isSearchActive) {
|
||||||
|
resetSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSearchEngine = engine;
|
||||||
|
localStorage.setItem('searchEngine', engine);
|
||||||
|
|
||||||
|
// 更新UI显示
|
||||||
|
updateSearchEngineUI();
|
||||||
|
|
||||||
|
// 关闭下拉菜单
|
||||||
|
searchEngineDropdown.classList.remove('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// 点击页面其他位置关闭下拉菜单
|
||||||
|
document.addEventListener('click', () => {
|
||||||
|
searchEngineDropdown.classList.remove('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新搜索引擎UI显示
|
||||||
|
function updateSearchEngineUI() {
|
||||||
|
// 移除所有选项的激活状态
|
||||||
|
searchEngineOptions.forEach(option => {
|
||||||
|
option.classList.remove('active');
|
||||||
|
|
||||||
|
// 如果是当前选中的搜索引擎,添加激活状态
|
||||||
|
if (option.getAttribute('data-engine') === currentSearchEngine) {
|
||||||
|
option.classList.add('active');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新搜索图标以反映当前搜索引擎
|
||||||
|
if (searchIcon) {
|
||||||
|
// 清除所有类,保留基本的search-icon类
|
||||||
|
const classList = searchIcon.className.split(' ').filter(cls => cls === 'search-icon');
|
||||||
|
searchIcon.className = classList.join(' ');
|
||||||
|
|
||||||
|
// 添加当前搜索引擎的图标类
|
||||||
|
const engine = searchEngines[currentSearchEngine];
|
||||||
|
if (engine) {
|
||||||
|
const iconClasses = engine.icon.split(' ');
|
||||||
|
iconClasses.forEach(cls => {
|
||||||
|
searchIcon.classList.add(cls);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新标题提示
|
||||||
|
searchIcon.setAttribute('title', engine.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行搜索(根据选择的搜索引擎)
|
||||||
|
function executeSearch(searchTerm) {
|
||||||
|
if (!searchTerm.trim()) return;
|
||||||
|
|
||||||
|
// 根据当前搜索引擎执行搜索
|
||||||
|
if (currentSearchEngine === 'local') {
|
||||||
|
// 执行本地搜索
|
||||||
|
performSearch(searchTerm);
|
||||||
|
} else {
|
||||||
|
// 使用外部搜索引擎
|
||||||
|
const engine = searchEngines[currentSearchEngine];
|
||||||
|
if (engine && engine.url) {
|
||||||
|
// 打开新窗口进行搜索
|
||||||
|
window.open(engine.url + encodeURIComponent(searchTerm), '_blank');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 搜索框事件处理
|
// 搜索框事件处理
|
||||||
searchInput.addEventListener('keyup', (e) => {
|
searchInput.addEventListener('keyup', (e) => {
|
||||||
if (e.key === 'Escape') {
|
if (e.key === 'Escape') {
|
||||||
searchInput.value = '';
|
searchInput.value = '';
|
||||||
resetSearch();
|
resetSearch();
|
||||||
} else if (e.key === 'Enter') {
|
} else if (e.key === 'Enter') {
|
||||||
performSearch(searchInput.value);
|
executeSearch(searchInput.value);
|
||||||
// 在移动设备上,执行搜索后自动关闭搜索面板
|
// 在移动设备上,执行搜索后自动关闭搜索面板
|
||||||
if (isMobile() && isSearchOpen) {
|
if (isMobile() && isSearchOpen) {
|
||||||
closeAllPanels();
|
closeAllPanels();
|
||||||
@@ -618,6 +761,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
// 初始化侧边栏状态
|
// 初始化侧边栏状态
|
||||||
initSidebarState();
|
initSidebarState();
|
||||||
|
|
||||||
|
// 初始化搜索引擎选择
|
||||||
|
initSearchEngine();
|
||||||
|
|
||||||
// 立即执行初始化,不再使用requestAnimationFrame延迟
|
// 立即执行初始化,不再使用requestAnimationFrame延迟
|
||||||
// 显示首页
|
// 显示首页
|
||||||
showPage('home');
|
showPage('home');
|
||||||
|
|||||||
@@ -92,8 +92,22 @@
|
|||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
<div class="search-box">
|
<div class="search-box">
|
||||||
<input type="text" id="search" placeholder="搜索...">
|
<input type="text" id="search" placeholder="搜索...">
|
||||||
|
<i class="fas fa-search search-icon" title="本地搜索"></i>
|
||||||
|
<div class="search-engine-dropdown">
|
||||||
|
<div class="search-engine-option" data-engine="local" title="本地搜索">
|
||||||
<i class="fas fa-search"></i>
|
<i class="fas fa-search"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="search-engine-option" data-engine="google" title="Google搜索">
|
||||||
|
<i class="fab fa-google"></i>
|
||||||
|
</div>
|
||||||
|
<div class="search-engine-option" data-engine="bing" title="Bing搜索">
|
||||||
|
<i class="fab fa-microsoft"></i>
|
||||||
|
</div>
|
||||||
|
<div class="search-engine-option" data-engine="baidu" title="百度搜索">
|
||||||
|
<i class="fas fa-paw"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 页面容器 -->
|
<!-- 页面容器 -->
|
||||||
|
|||||||
Reference in New Issue
Block a user