1
0

添加搜索功能

This commit is contained in:
2022-03-06 23:55:25 +08:00
parent 82392a72e4
commit 9f14383eae
5 changed files with 320 additions and 31 deletions

View File

@@ -30,6 +30,37 @@ html, body, #app {
-webkit-tap-highlight-color: transparent;
}
.float-btn {
display: flex;
align-items: center;
justify-content: center;
width: 2.25rem;
height: 2.25rem;
box-shadow:
0 0.15rem 0.15rem 0 rgba(0, 0, 0, 0.14),
0 0.2rem 0.1rem -0.15rem rgba(0, 0, 0, 0.12),
0 0.1rem 0.3rem 0 rgba(0, 0, 0, 0.2);
border-radius: 0.25rem;
background-color: var(--color-green);
color: #FFF;
font-size: 1rem;
line-height: 1;
cursor: pointer;
&:hover .cover {
opacity: 0.2;
}
.cover {
position: absolute;
width: 100%;
height: 100%;
background-color: #FFF;
opacity: 0;
transition: opacity 0.25s;
}
}
/* Buefy */
// 导航栏

View File

@@ -0,0 +1,28 @@
<template>
<div class="float-btn btn-search" @click="toggleSearch()">
<b-icon icon="magnify"></b-icon>
<div class="cover"></div>
</div>
</template>
<script>
export default {
name: 'BtnSearch',
methods: {
/** 显示搜索面板 */
toggleSearch() {
this.$emit('show-search');
},
},
}
</script>
<style lang="less" scoped>
.btn-search {
position: fixed;
bottom: 5rem;
right: 2rem;
}
</style>

View File

@@ -1,5 +1,5 @@
<template>
<div class="to-top" @click="scrollToTop()">
<div class="float-btn btn-to-top" @click="scrollToTop()">
<b-icon icon="arrow-up"></b-icon>
<div class="cover"></div>
</div>
@@ -7,7 +7,7 @@
<script>
export default {
name: 'ToTop',
name: 'BtnToTop',
props: {
/** 滚动的元素 */
@@ -41,37 +41,9 @@ export default {
</script>
<style lang="less" scoped>
.to-top {
display: flex;
align-items: center;
justify-content: center;
.btn-to-top {
position: fixed;
bottom: 2rem;
right: 2rem;
width: 2.25rem;
height: 2.25rem;
box-shadow:
0 0.15rem 0.15rem 0 rgba(0, 0, 0, 0.14),
0 0.2rem 0.1rem -0.15rem rgba(0, 0, 0, 0.12),
0 0.1rem 0.3rem 0 rgba(0, 0, 0, 0.2);
border-radius: 0.25rem;
background-color: var(--color-green);
color: #FFF;
font-size: 1rem;
line-height: 1;
cursor: pointer;
&:hover .cover {
opacity: 0.2;
}
}
.cover {
position: absolute;
width: 100%;
height: 100%;
background-color: #FFF;
opacity: 0;
transition: opacity 0.25s;
}
</style>

View File

@@ -0,0 +1,233 @@
<template>
<div
v-show="isShow"
class="search-panel"
@click="close()"
>
<!-- 遮罩 -->
<div class="panel-cover"></div>
<!-- 面板 -->
<div class="panel-content">
<b-input
ref="searchInput"
v-model="searchWords"
type="search"
class="search-input"
icon="magnify"
icon-clickable
@icon-click="search()"
@click.native.stop
@keydown.native.enter="search()"
></b-input>
<div class="search-result">
<div
v-for="(item, index) in searchResult"
:key="index + '_' + item.itemName"
:title="item.itemLabel"
class="result-item"
@click.stop="changePage(item.categoryName, item.itemName)"
>
<span class="item-title">{{ item.itemLabel }}</span>
<b-tag
class="item-tag"
type="is-primary is-light"
rounded
>{{ item.categoryLabel }}</b-tag>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SearchPanel',
props: {
/** 是否显示 */
isShow: {
type: Boolean,
default: false
},
/** 内容列表 */
itemList: {
type: Array,
default() {
return [];
}
},
},
data() {
return {
/** 搜索关键词 */
searchWords: '',
/** 搜索结果 */
searchResult: [],
}
},
watch: {
// 自动聚焦
isShow: {
handler(value) {
if (!value) {
return;
}
setTimeout(() => {
/** @type {HTMLInputElement} */
const el = this.$refs['searchInput'];
if (el) {
el.focus();
}
}, 200);
}
},
// 自动清空搜索结果
searchWords: {
handler(value) {
if (!value) {
this.search();
}
}
},
},
methods: {
/** 跳转页面 */
changePage(categoryName, itemName) {
this.$emit('change-page', categoryName, itemName);
this.close();
},
/** 关闭面板 */
close() {
this.$emit('close');
},
/** 搜索 */
search() {
const items = this.itemList;
const keyword = this.searchWords.toLowerCase();
if (keyword) {
this.searchResult = items.filter((item) => {
/** @type {string} */
const itemName = (item['itemName'] || '').toLowerCase();
/** @type {string} */
const itemLabel = (item['itemLabel'] || '').toLowerCase();
return (itemName.includes(keyword) || itemLabel.includes(keyword));
});
} else {
this.searchResult = [];
}
},
},
}
</script>
<style lang="less" scoped>
.search-panel {
display: flex;
justify-content: center;
position: fixed !important;
top: 0;
left: 0;
z-index: 1000;
width: 100%;
height: 100%;
}
.panel-cover {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
backdrop-filter: blur(0.25rem);
opacity: 0.5;
}
.panel-content {
display: flex;
flex-direction: column;
position: relative;
padding: 2rem;
width: 100%;
max-width: 32rem;
.search-input {
position: relative;
flex-shrink: 0;
}
.search-result {
position: relative;
flex-grow: 1;
margin-top: 1rem;
height: 0;
overflow-y: auto;
&::-webkit-scrollbar {
display: none;
}
}
.result-item {
display: flex;
align-items: center;
margin-bottom: 1rem;
padding: 0.5rem 0.75rem;
border-radius: 0.25rem;
background-color: #FFF;
font-size: 0.875rem;
line-height: 1;
transition: opacity 0.25s;
cursor: pointer;
&:hover {
opacity: 0.8;
}
.item-title {
display: inline-block;
flex-grow: 1;
width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.item-tag {
flex-shrink: 0;
margin-left: 1em;
}
}
}
</style>

View File

@@ -82,11 +82,24 @@
/>
</template>
<!-- 搜索 -->
<btn-search
@show-search="toggleSearch(true)"
/>
<!-- 返回顶部 -->
<btn-to-top />
</div>
<!-- 搜索面板 -->
<search-panel
:is-show="isShowSearch"
:item-list="contentListAll"
@change-page="changePage"
@close="toggleSearch(false)"
/>
</div>
</template>
@@ -94,16 +107,20 @@
import { setTitle, toast } from '@/assets/js/utils';
import { getContentFile } from '@/request/index';
import BtnSearch from '@/components/BtnSearch';
import BtnToTop from '@/components/BtnToTop';
import ContentIndex from '@/components/ContentIndex';
import MarkdownParser from '@/components/MarkdownParser';
import SearchPanel from '@/components/SearchPanel';
export default {
name: 'ContentView',
components: {
BtnSearch,
BtnToTop,
ContentIndex,
MarkdownParser,
SearchPanel,
},
data() {
return {
@@ -114,6 +131,9 @@ export default {
/** 是否正在载入内容 */
isLoading: false,
/** 是否显示搜索面板 */
isShowSearch: false,
/** 是否在移动端显示侧边栏 */
isShowSidebar: false,
@@ -319,6 +339,11 @@ export default {
this.isLoading = isLoading;
},
/** 切换显示隐藏搜索面板 */
toggleSearch(isShow = false) {
this.isShowSearch = isShow;
},
/** 切换侧边栏显示隐藏 */
toggleSidebar() {
this.isShowSidebar = !this.isShowSidebar;