-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
69 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,24 +4,20 @@ | |
<svg | ||
class="icon kano-icon dark:dark-icon w-8 icon-hover" | ||
aria-hidden="false" | ||
@click.stop="settingHandler" | ||
> | ||
@click.stop="settingHandler"> | ||
<use xlink:href="#icon-settings" class="rotate"></use> | ||
</svg> | ||
</div> | ||
<div ref="searchEle" class="search relative flex flex-col"> | ||
<div | ||
class="search-engine flex overflow-hidden dark:dark-search-engine" | ||
ref="searchEngineElement" | ||
> | ||
ref="searchEngineElement"> | ||
<div | ||
class="flex items-center" | ||
id="engine_switch_btn" | ||
@click.stop="switchEngine" | ||
> | ||
@click.stop="switchEngine"> | ||
<i | ||
:class="`icon kano-icon dark:dark-kano-icon iconfont dark:dark-icon ${selectedEngine.icon}`" | ||
></i> | ||
:class="`icon kano-icon dark:dark-kano-icon iconfont dark:dark-icon ${selectedEngine.icon}`"></i> | ||
</div> | ||
<input | ||
ref="searchBox" | ||
|
@@ -37,20 +33,17 @@ | |
@focusout.stop="showHideSearchHistory" | ||
@mouseleave.stop="eventMouse" | ||
class="input pl-3 box-border outline-none dark:input-dark" | ||
:placeholder="`在${selectedEngine.name}上搜索`" | ||
/> | ||
:placeholder="`在${selectedEngine.name}上搜索`" /> | ||
<div | ||
class="clear-input" | ||
@click.stop="clearContent" | ||
v-show="searchContent" | ||
> | ||
v-show="searchContent"> | ||
<i class="iconfont dark:dark:dark-text icon-close icon close"></i> | ||
</div> | ||
<button | ||
id="searchbtn" | ||
class="search-btn flex justify-center items-center dark:hover:dark-hover-bg" | ||
@click.stop="startSearch(undefined, true)" | ||
> | ||
@click.stop="startSearch(undefined, true)"> | ||
<svg class="icon" aria-hidden="false" height="30px"> | ||
<use xlink:href="#icon-search"></use> | ||
</svg> | ||
|
@@ -61,10 +54,9 @@ | |
@mouseenter.stop="suggestActiveControl" | ||
@mouseleave.stop="suggestActiveControl" | ||
class="search-suggestion top-border absolute dark:dark-suggest-bg" | ||
v-show=" | ||
v-if=" | ||
(suggestWords.length && suggestIsShow) || isSearchEngineListMode | ||
" | ||
> | ||
"> | ||
<ul ref="scrollUl"> | ||
<transition-group name="suggestion-ul"> | ||
<li | ||
|
@@ -73,16 +65,14 @@ | |
:class="{ active: item.isSelected }" | ||
@click.stop="startSearch(item.title)" | ||
v-for="(item, index) in suggestWords" | ||
:key="index" | ||
> | ||
:key="index"> | ||
<span class="searchkey" :id="`key_${index}_${Math.random()}`">{{ | ||
item.title | ||
}}</span> | ||
<i | ||
v-show="item.allowDel" | ||
@click.stop.prevent="delHistory(index)" | ||
class="iconfont icon-close icon close" | ||
></i> | ||
class="iconfont icon-close icon close"></i> | ||
</li> | ||
<!-- 搜索引擎切换列表 --> | ||
<li v-else class="searchEngineListBox"> | ||
|
@@ -104,46 +94,27 @@ | |
* @Email: [email protected] | ||
* @Date: 2023-04-17 14:47:15 | ||
* @Last Modified by: kanoqwq | ||
* @Last Modified time: 2024-11-07 17:21:19 | ||
* @Last Modified time: 2024-11-07 20:18:03 | ||
* @Description: Description | ||
*/ | ||
import { ref, reactive, watch, computed, onMounted } from "vue"; | ||
import Settings from "./Settings.vue"; | ||
import SearchEngines from "@/components/SearchEngines/index.vue"; | ||
import throttle from "lodash/throttle"; | ||
import { suggestAPI } from "@/utils/searchSuggestions"; | ||
import useStore from "@/store"; | ||
import { SearchEngine, SuggestWords } from "@/types/global"; | ||
import Favorites from "./Favorites/Favorites.vue"; | ||
import { openWithoutReferrer } from "@/utils/openLink"; | ||
onMounted(() => { | ||
window.onkeyup = (e: KeyboardEvent) => { | ||
e.preventDefault(); | ||
if (e.key == "Alt") { | ||
if (isSearchFocused.value) { | ||
searchBox.value.blur(); | ||
searchBlur(); | ||
uncheckSuggestWords(); | ||
isSearchFocused.value = false; | ||
} else { | ||
searchBox.value.focus(); | ||
} | ||
} | ||
if (e.key == "Escape") { | ||
searchBox.value.blur(); | ||
} | ||
}; | ||
}); | ||
const emit = defineEmits(["blur", "focus"]); | ||
import { ref, reactive, watch, computed, onMounted } from 'vue'; | ||
import Settings from './Settings.vue'; | ||
import SearchEngines from '@/components/SearchEngines/index.vue'; | ||
import throttle from 'lodash/throttle'; | ||
import { suggestAPI } from '@/utils/searchSuggestions'; | ||
import useStore from '@/store'; | ||
import { SearchEngine, SuggestWords } from '@/types/global'; | ||
import Favorites from './Favorites/Favorites.vue'; | ||
import { openWithoutReferrer } from '@/utils/openLink'; | ||
const emit = defineEmits(['blur', 'focus']); | ||
//store | ||
const historySearch = useStore.historySearch(); | ||
const searchEnginesStore = useStore.searchEngines(); | ||
// const global = inject(globalKey) | ||
let searchContent = ref(""); | ||
let searchContent = ref(''); | ||
let engineId: number = searchEnginesStore.selectedEngine; | ||
let selectedEngine = reactive<SearchEngine>({ | ||
...(searchEnginesStore.searchEngines.find((i) => i.id == engineId) || | ||
|
@@ -159,6 +130,22 @@ const settingsIsShow = ref(false); | |
const filterWords = computed(() => Configs.formattedFilterWords); | ||
const isSearchFocused = ref(false); | ||
onMounted(() => { | ||
window.onkeyup = (e: KeyboardEvent) => { | ||
e.preventDefault(); | ||
if (e.key == 'Alt') { | ||
if (isSearchFocused.value) { | ||
containerClick({} as any); | ||
} else { | ||
searchBox.value.focus(); | ||
} | ||
} | ||
if (e.key == 'Escape') { | ||
containerClick({} as any); | ||
} | ||
}; | ||
}); | ||
watch( | ||
() => searchEnginesStore.selectedEngine, | ||
(id) => { | ||
|
@@ -191,10 +178,10 @@ const containerClick = (e: Event) => { | |
uncheckSuggestWords(); | ||
searchBox.value.blur(); | ||
searchBlur(); | ||
uncheckSuggestWords(); | ||
isSearchEngineListMode.value = false; | ||
suggestIsShow.value = false; | ||
isSearchFocused.value = false; | ||
suggestIsShow.value = false; | ||
suggestIsShow.value = false; | ||
}; | ||
watch([suggestWords, suggestIsShow, searchContent, suggestActive], () => { | ||
|
@@ -222,7 +209,7 @@ const startSearch = ( | |
/^(ht|f)tp(s?)\:\/\/[0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*(:(0-9)*)*(\/?)([a-zA-Z0-9\-\.\?\,\'\/\\\+&%\$#_]*)?$/; | ||
let reqUrl = | ||
selectedEngine.url + encodeURIComponent(keyWord) + " " + filterWords.value; | ||
selectedEngine.url + encodeURIComponent(keyWord) + ' ' + filterWords.value; | ||
if (keyWord.trim() !== searchContent.value.trim()) { | ||
searchContent.value = keyWord.trim(); | ||
|
@@ -232,7 +219,7 @@ const startSearch = ( | |
try { | ||
scrollUl.value.children[0].scrollIntoView({ | ||
top: 0, | ||
behavior: "instant", | ||
behavior: 'instant', | ||
}); | ||
} catch {} | ||
|
@@ -263,16 +250,16 @@ const startSearch = ( | |
const searchEngineElement = ref<HTMLFormElement>(); | ||
const toggleShadow = (flag: boolean) => { | ||
searchEngineElement.value?.classList?.[flag ? "add" : "remove"]("shadow"); | ||
searchEngineElement.value?.classList?.[flag ? "add" : "remove"]( | ||
"dark:dark-shadow" | ||
searchEngineElement.value?.classList?.[flag ? 'add' : 'remove']('shadow'); | ||
searchEngineElement.value?.classList?.[flag ? 'add' : 'remove']( | ||
'dark:dark-shadow' | ||
); | ||
}; | ||
// 鼠标滑过改变阴影 | ||
const eventMouse = (e: MouseEvent): void => { | ||
if (e.type == "mouseenter" && !isSearchFocused.value) { | ||
if (e.type == 'mouseenter' && !isSearchFocused.value) { | ||
if (isSearchEngineListMode.value) { | ||
toggleShadow(false); | ||
return; | ||
|
@@ -296,8 +283,8 @@ const enterEvent = (): void => { | |
const searchBlur = () => { | ||
if (Configs.searchTransitonEnabled) { | ||
searchEle.value.style.top = ""; | ||
emit("blur"); | ||
searchEle.value.style.top = ''; | ||
emit('blur'); | ||
} | ||
isSearchFocused.value = false; | ||
searchBox.value.blur(); | ||
|
@@ -311,8 +298,8 @@ const searchEle = ref(); | |
const focus = () => { | ||
if (Configs.searchTransitonEnabled) { | ||
searchEle.value.style.top = "33%"; | ||
emit("focus"); | ||
searchEle.value.style.top = '33%'; | ||
emit('focus'); | ||
} | ||
toggleShadow(false); | ||
suggestIsShow.value = true; | ||
|
@@ -325,7 +312,7 @@ const focus = () => { | |
//搜索建议(谷歌接口暂时无法支持跨域) | ||
const searchSuggestion = throttle( | ||
async ( | ||
method: "suggestBaidu" | "suggestBing" | "suggestDuckDuckGo" | ||
method: 'suggestBaidu' | 'suggestBing' | 'suggestDuckDuckGo' | ||
): Promise<void> => { | ||
try { | ||
//清除阴影 | ||
|
@@ -351,7 +338,7 @@ const searchSuggestion = throttle( | |
suggestWords.value = [...historySearch.gethistorySearchList]; | ||
} | ||
} catch (e) { | ||
console.log("搜索建议获取失败"); | ||
console.log('搜索建议获取失败'); | ||
} | ||
}, | ||
100 | ||
|
@@ -361,7 +348,7 @@ const searchSuggestion = throttle( | |
const clearContent = (): void => { | ||
isSuggestMode = false; | ||
suggestWords.value.length = 0; | ||
searchContent.value = ""; | ||
searchContent.value = ''; | ||
}; | ||
const scrollUl = ref(); | ||
|
@@ -372,9 +359,9 @@ watch(suggestionIndex, () => { | |
if (isScrollingToTop.value) return; | ||
try { | ||
scrollUl.value.children[suggestionIndex.value].scrollIntoView({ | ||
behavior: "smooth", | ||
block: "start", | ||
inline: "nearest", | ||
behavior: 'smooth', | ||
block: 'start', | ||
inline: 'nearest', | ||
}); | ||
} catch {} | ||
}); | ||
|
@@ -392,7 +379,7 @@ const moveSuggestion = (e: KeyboardEvent): void => { | |
//候选词列表不为空 | ||
if (suggestWords.value.length != 0) { | ||
if (key == "ArrowUp") { | ||
if (key == 'ArrowUp') { | ||
//阻止上下按键操作光标 | ||
e.preventDefault(); | ||
if (suggestionIndex.value == 0 || suggestionIndex.value == -1) { | ||
|
@@ -402,7 +389,7 @@ const moveSuggestion = (e: KeyboardEvent): void => { | |
(suggestionIndex.value - 1) % suggestWords.value.length; | ||
} | ||
removeandInit(); | ||
} else if (key == "ArrowDown") { | ||
} else if (key == 'ArrowDown') { | ||
e.preventDefault(); | ||
if (suggestWords.value.length - 1 == suggestionIndex.value) { | ||
suggestionIndex.value = 0; | ||
|
@@ -411,18 +398,18 @@ const moveSuggestion = (e: KeyboardEvent): void => { | |
(suggestionIndex.value + 1) % suggestWords.value.length; | ||
} | ||
removeandInit(); | ||
} else if (key == "Home") { | ||
} else if (key == 'Home') { | ||
e.preventDefault(); | ||
suggestionIndex.value = 0; | ||
removeandInit(); | ||
} else if (key == "End") { | ||
} else if (key == 'End') { | ||
e.preventDefault(); | ||
suggestionIndex.value = suggestWords.value.length - 1; | ||
removeandInit(); | ||
} | ||
} | ||
//del按下可以快速删除历史 | ||
if (key == "Delete") { | ||
if (key == 'Delete') { | ||
//防止误删搜索建议中的内容 | ||
if (suggestWords.value.length != 0 && !isSuggestMode) { | ||
historySearch.deleteHistory(suggestionIndex.value); | ||
|
@@ -457,7 +444,7 @@ let showHideTimer: any = null; | |
const showHideSearchHistory = (e: Event) => { | ||
showHideTimer && clearTimeout(showHideTimer); | ||
showHideTimer = setTimeout(() => { | ||
if (e.type == "focusin") { | ||
if (e.type == 'focusin') { | ||
focus(); | ||
isSearchEngineListMode.value = false; | ||
} else { | ||
|
@@ -472,7 +459,7 @@ const showHideSearchHistory = (e: Event) => { | |
//判定鼠标是否在搜索历史框内 | ||
const suggestActiveControl = (e: Event) => { | ||
if (e.type == "mouseenter") { | ||
if (e.type == 'mouseenter') { | ||
suggestActive.value = true; | ||
} else { | ||
suggestActive.value = false; | ||
|
@@ -482,7 +469,7 @@ const suggestActiveControl = (e: Event) => { | |
//删除搜索历史 | ||
const delHistory = (index: number) => { | ||
focus(); | ||
emit("focus"); | ||
emit('focus'); | ||
suggestWords.value.splice(index, 1); | ||
historySearch.deleteHistory(index); | ||
//删空后将搜索框设为圆角边框 | ||
|
@@ -499,8 +486,8 @@ const settingHandler = () => { | |
//切换搜索的下边框 | ||
const toggleSearchBorder = (active: boolean) => { | ||
searchEngineElement.value?.classList[active ? "remove" : "add"]( | ||
"search-engine-active" | ||
searchEngineElement.value?.classList[active ? 'remove' : 'add']( | ||
'search-engine-active' | ||
); | ||
}; | ||
|
@@ -511,5 +498,5 @@ defineExpose({ | |
</script> | ||
|
||
<style scoped lang="less"> | ||
@import url("./Search.less"); | ||
@import url('./Search.less'); | ||
</style> |