You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bloggingplatform/vue/src/components/BlogSearch.vue

268 lines
7.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<!-- 搜索区域 -->
<div v-if="!showResults" class="search-component">
<input type="text" v-model="searchTerm" placeholder="请输入搜索词" />
<button @click="performSearch">搜索</button>
</div>
<!-- 搜索结果展示区域 -->
<div v-if="showResults" class="search-results-page">
<!-- 搜索词展示 -->
<div class="search-term-display">
<h2>搜索结果:“{{ searchTerm }}”</h2>
</div>
<!-- 排序与筛选区域 -->
<div class="sort-filter-area">
<!-- 排序方式选择 -->
<div class="sort-by">
<label for="sort-select">排序方式:</label>
<select id="sort-select" v-model="sortBy">
<option value="relevance">相关性</option>
<option value="publishDate-desc">发布日期(最新)</option>
<option value="publishDate-asc">发布日期(最旧)</option>
<option value="popularity">热度</option>
</select>
</div>
<!-- 筛选条件选择 -->
<div class="filter-by">
<label for="category-select">文章类别:</label>
<select id="category-select" v-model="filterConditions.category">
<option value="">全部</option>
<option value="food">美食</option>
<option value="travel">旅游</option>
<option value="technology">科技</option>
</select>
<label for="time-range-select">时间范围:</label>
<select id="time-range-select" v-model="filterConditions.timeRange">
<option value="">全部</option>
<option value="this-week">本周</option>
<option value="this-month">本月</option>
<option value="this-year">本年内</option>
</select>
</div>
<!-- 应用筛选与排序按钮 -->
<button @click="applyFilter">应用筛选</button>
<button @click="sortResults">排序</button>
</div>
<!-- 搜索结果列表展示 -->
<div class="result-list-area">
<ul>
<li v-for="(result, index) in searchResults" :key="index">
<!-- -->
<h3 v-html="result.title | highlight(searchTerm)"></h3>
<p v-html="result.summary | highlight(searchTerm)"></p>
<p>发布日期:{{ result.publishDate }}</p>
</li>
</ul>
</div>
<!-- 最下面一排的导航按钮 -->
<div class="bottom-navigation">
<button @click="goToPreviousPage" :disabled="currentPage === 1">上一页</button>
<span>第{{ currentPage }}页 / 共{{ totalPages }}页</span>
<button @click="goToNextPage" :disabled="currentPage === totalPages">下一页</button>
<button @click="goBackToSearch">返回搜索</button>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'BlogSearch',
data() {
return {
searchTerm: '',
showResults: false,
searchResults: [],
sortBy: 'relevance',
filterConditions: {
category: '',
timeRange: ''
},
currentPage: 1,
totalPages: 1,
resultsPerPage: 10
};
},
filters: {
highlight: function (text, searchTerm) {
if (!searchTerm) return text;
const re = new RegExp(searchTerm, 'gi');
return text.replace(re, '<span style="color:red;">$&</span>');
}
},
methods: {
performSearch() {
//
if (!this.searchTerm.trim()) {
alert('');
return;
}
// true便
this.showResults = true;
//
this.getSearchResults();
},
async getSearchResults() {
try {
//
const response = await axios.get('/api/search', {
params: {
page: this.currentPage,
sortBy: this.sortBy,
category: this.filterConditions.category,
timeRange: this.filterConditions.timeRange,
searchTerm: this.searchTerm
}
});
this.searchResults = response.data.results;
this.totalPages = Math.ceil(response.data.totalCount / this.resultsPerPage);
} catch (error) {
console.error('', error);
}
},
sortResults() {
//
if (this.sortBy === 'publishDate-desc') {
this.searchResults.sort((a, b) => new Date(b.publishDate) - new Date(a.publishDate));
} else if (this.sortBy === 'publishDate-asc') {
this.searchResults.sort((a, b) => new Date(a.publishDate) - new Date(b.publishDate));
} else if (this.sortBy === 'popularity') {
// 假设文章对象有一个popularity属性用于表示热度
this.searchResults.sort((a, b) => b.popularity - a.popularity);
}
},
applyFilter() {
// 应用筛选条件后重新获取搜索结果并重置当前页码为1
this.currentPage = 1;
this.getSearchResults();
},
goToPreviousPage() {
if (this.currentPage > 1) {
this.currentPage--;
this.getSearchResults();
}
},
goToNextPage() {
if (this.currentPage < this.totalPages) {
this.currentPage++;
this.getSearchResults();
}
},
goBackToSearch() {
// 重置相关数据并隐藏搜索结果区域,返回搜索状态
this.searchTerm = '';
this.showResults = false;
this.sortBy = 'relevance';
this.filterConditions = {
category: '',
timeRange: ''
};
this.currentPage = 1;
this.totalPages = 1;
this.searchResults = [];
}
},
mounted() {
// 如果是通过路由参数进入此页面且有搜索词参数,自动执行搜索操作
if (this.$route.params.searchTerm) {
this.searchTerm = this.$route.params.searchTerm;
this.showResults = true;
this.getSearchResults();
}
}
};
</script>
<style>
.search-component {
margin: 20px;
display: flex;
justify-content: center;
align-items: center;
}
input[type="text"] {
padding: 10px;
width: 300px;
border: 1px solid #ccc;
border-radius: 5px;
margin-right: 10px;
}
button {
padding: 10px 20px;
background-color: #007BFF;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
.search-results-page {
font-family: Arial, sans-serif;
padding: 20px;
}
.search-term-display {
margin-bottom: 10px;
}
.sort-filter-area {
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.sort-by,
.filter-by {
margin-bottom: 10px;
}
.sort-by label,
.filter-by label {
margin-right: 10px;
}
.result-list-area ul {
list-style: none;
padding: 0;
margin: 0;
}
.result-list-area li {
border-bottom: 1px solid #ccc;
padding-bottom: 10px;
margin-bottom: 10px;
}
.pagination-area {
margin-top: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
.back-button-area {
margin-top: 20px;
}
.bottom-navigation {
margin-top: 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #ccc;
padding-top: 20px;
}
</style>