Compare commits

..

3 Commits

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/bloggingplatform.iml" filepath="$PROJECT_DIR$/.idea/bloggingplatform.iml" />
</modules>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

23
vue/.gitignore vendored

@ -0,0 +1,23 @@
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"baseUrl": "./",
"moduleResolution": "node",
"paths": {
"@/*": [
"src/*"
]
},
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
}
}

11576
vue/package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,44 @@
{
"name": "bloggingplatform",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^1.7.7",
"core-js": "^3.8.3",
"vue": "^3.2.13"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

@ -0,0 +1,26 @@
<template>
<img alt="Vue logo" src="./assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

@ -0,0 +1,268 @@
<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>

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

@ -0,0 +1,4 @@
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
})

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