搜索页面大概框架,暂无功能

search-results-page
黄佳程 1 week ago
parent 46cbf46b55
commit 84605266ff

11576
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -8,6 +8,7 @@
"lint": "vue-cli-service lint" "lint": "vue-cli-service lint"
}, },
"dependencies": { "dependencies": {
"axios": "^1.7.7",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"vue": "^3.2.13" "vue": "^3.2.13"
}, },

@ -0,0 +1,262 @@
<template>
<!-- 搜索区域 -->
<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="pagination-area">
<button @click="goToPreviousPage" :disabled="currentPage === 1">上一页</button>
<span>{{ currentPage }} / {{ totalPages }}</span>
<button @click="goToNextPage" :disabled="currentPage === totalPages">下一页</button>
</div>
<!-- 返回相关区域 -->
<div class="back-button-area">
<button @click="goBackToSearch"></button>
</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;
}
</style>

@ -1,58 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

@ -1,4 +1,4 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue' // import App from './App.vue'
import App from './components/BlogSearch.vue'
createApp(App).mount('#app') createApp(App).mount('#app')

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save