Snavigation/src/components/SearchInp.vue
2023-07-30 18:39:43 +08:00

233 lines
5.6 KiB
Vue

<template>
<div class="search-input" @click.stop>
<div
v-if="status.siteStatus === 'focus'"
class="mask"
@click="closeSearchInput"
/>
<div
:class="status.siteStatus === 'focus' ? 'all focus' : 'all'"
:style="{ pointerEvents: inputClickable ? 'none' : 'auto' }"
ref="searchAllRef"
>
<div class="engine" title="切换搜索引擎">
<SvgIcon iconName="icon-baidu" className="baidu" />
</div>
<input
class="input"
id="main-input"
ref="searchInputRef"
type="text"
label="search"
title="请输入搜索内容"
autocomplete="false"
:placeholder="inputTip"
v-model="inputValue"
@focus="status.setSiteStatus('focus')"
@keydown.stop="pressKeyboard"
/>
<div class="go" title="搜索" @click="toSearch(inputValue)">
<SvgIcon iconName="icon-search" className="search" />
</div>
</div>
<!-- 搜索建议 -->
<Suggestions
ref="suggestionsRef"
:keyWord="inputValue"
@toSearch="toSearch"
/>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import { statusStore, setStore } from "@/stores";
import { usePush } from "notivue";
import Suggestions from "@/components/Suggestions.vue";
const set = setStore();
const status = statusStore();
const push = usePush();
// 搜索框配置
const inputTip = import.meta.env.VITE_INPUT_TIP ?? "想要搜点什么";
// 搜索框数据
const searchAllRef = ref(null);
const searchInputRef = ref(null);
const inputClickable = ref(true);
const inputValue = ref("");
// 搜索建议子组件
const suggestionsRef = ref(null);
// 关闭搜索框
const closeSearchInput = () => {
status.setSiteStatus("normal");
searchInputRef.value?.blur();
inputValue.value = "";
};
// 前往搜索
const toSearch = (val, type = 1) => {
const searchValue = val?.trim();
// 定义跳转方法
const jumpLink = (url) => {
if (set.urlJumpType === "open") {
window.location.href = url;
} else if (set.urlJumpType === "href") {
window.open(url, "_blank");
}
};
// 是否为空
if (searchValue) {
console.log("前往搜索:" + searchValue, type);
// type
// 1 默认 / 2 快捷翻译 / 3 电子邮件 / 4 直接访问
// 切换搜索引擎还没写,先这样
switch (type) {
case 1:
jumpLink(`https://www.bing.com/search?q=${searchValue}`);
break;
case 2:
jumpLink(`https://fanyi.baidu.com/#en/zh/${searchValue}`);
break;
case 3:
jumpLink(`mailto:${searchValue}`);
break;
case 4:
const urlRegex = /^(https?:\/\/)/i;
const url = urlRegex.test(searchValue)
? searchValue
: `//${searchValue}`;
jumpLink(url);
break;
default:
break;
}
closeSearchInput();
} else {
status.setSiteStatus("focus");
searchInputRef.value?.focus();
push.info({ message: "请输入搜索内容", duration: 1000 });
}
};
// 搜索框 Dom 操作
const searchInputDom = (dom) => {
if (!dom) return false;
dom.addEventListener("animationstart", () => {
console.log("动画开始");
inputClickable.value = true;
});
dom.addEventListener("animationend", () => {
console.log("动画结束");
inputClickable.value = false;
// 自动 focus
if (set.autoFocus) {
status.setSiteStatus("focus");
searchInputRef.value?.focus();
}
});
};
// 键盘事件
const pressKeyboard = (event) => {
// 获取键的键码
const keyCode = event.keyCode;
// 13 回车
if (keyCode === 13) toSearch();
// 子组件事件
suggestionsRef.value?.keyboardEvents(keyCode, event);
};
onMounted(() => {
searchInputDom(searchAllRef.value);
});
</script>
<style lang="scss" scoped>
.search-input {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
max-width: 680px;
width: calc(100% - 60px);
.mask {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
.all {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
height: 42px;
width: 100%;
border-radius: 30px;
color: var(--main-text-color);
background-color: var(--main-background-color);
backdrop-filter: blur(10px);
opacity: 1;
animation: fade-up-in 0.7s cubic-bezier(0.37, 0.99, 0.36, 1);
transition: transform 0.3s, background-color 0.3s;
z-index: 1;
&.focus {
transform: translateY(-50px);
background-color: var(--main-background-hover-color);
.input {
color: var(--main-text-hover-color);
&::placeholder {
opacity: 0;
}
}
.engine,
.go,
.delete {
color: var(--main-text-hover-color);
}
}
.input {
display: flex;
justify-content: center;
height: 100%;
width: 100%;
padding: 0;
margin: 0;
border: none;
outline: none;
background: none;
font-size: 16px;
color: var(--main-text-color);
&::placeholder {
text-align: center;
transform: translateY(1px);
color: var(--main-text-color);
letter-spacing: 2px;
transition: opacity 0.3s;
}
}
.engine,
.go {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 64px;
font-size: 20px;
border-radius: 30px;
transition: background-color 0.3s;
&:hover {
background-color: var(--main-background-color);
}
}
}
}
</style>