豆宝社区项目实战教程简介
本项目实战教程配有免费视频教程,配套代码完全开源。手把手从零开始搭建一个目前应用最广泛的Springboot+Vue前后端分离多用户社区项目。本项目难度适中,为便于大家学习,每一集视频教程对应在Github上的每一次提交。
项目首页截图
代码开源地址
视频教程地址
前端技术栈
Vue
Vuex
Vue Router
Axios
Bulma
Buefy
Element
Vditor
DarkReader
后端技术栈
Spring Boot
Mysql
Mybatis
MyBatis-Plus
Spring Security
JWT
Lombok
搜索前端实现
API
src\api\新增search.js
import request from '@/utils/request'
// 关键词检索
export function searchByKeyword(query) {
return request({
url: `/search`,
method: 'get',
params: {
keyword: query.keyword,
pageNum: query.pageNum,
pageSize: query.pageSize
}
})
}
复制代码
路由
src\router\index.js
,
// 搜索
{
name: 'search',
path: '/search',
component: () => import('@/views/Search'),
meta: { title: '检索' }
}
复制代码
新增Search.vue
src/views/Search
<template>
<div>
<el-card shadow="never">
<div slot="header" class="clearfix">
检索到 <code>{{ list.length }}</code>
条关于 <code class="has-text-info">{{ query.keyword }}</code> 的记录
</div>
<div>
<article v-for="(item, index) in list" :key="index" class="media">
<div class="media-left">
<figure class="image is-48x48">
<img :src="`https://cn.gravatar.com/avatar/${item.userId}?s=164&d=monsterid`">
</figure>
</div>
<div class="media-content">
<div class="">
<p class="ellipsis is-ellipsis-1">
<el-tooltip class="item" effect="dark" :content="item.title" placement="top">
<router-link :to="{name:'post-detail',params:{id:item.id}}">
<span class="is-size-6">{{ item.title }}</span>
</router-link>
</el-tooltip>
</p>
</div>
<nav class="level has-text-grey is-mobile is-size-7 mt-2">
<div class="level-left">
<div class="level-left">
<router-link class="level-item" :to="{ path: `/member/${item.username}/home` }">
{{ item.alias }}
</router-link>
<span class="mr-1">
发布于:{{ dayjs(item.createTime).format("YYYY/MM/DD") }}
</span>
<span
v-for="(tag, index) in item.tags"
:key="index"
class="tag is-hidden-mobile is-success is-light mr-1"
>
<router-link :to="{ name: 'tag', params: { name: tag.name } }">
{{ "#" + tag.name }}
</router-link>
</span>
<span class="is-hidden-mobile">浏览:{{ item.view }}</span>
</div>
</div>
</nav>
</div>
<div class="media-right" />
</article>
</div>
<!--分页-->
<pagination
v-show="query.total > 0"
:total="query.total"
:page.sync="query.pageNum"
:limit.sync="query.pageSize"
@pagination="fetchList"
/>
</el-card>
</div>
</template>
<script>
import { searchByKeyword } from '@/api/search'
import Pagination from '@/components/Pagination'
export default {
name: 'Search',
components: { Pagination },
data() {
return {
list: [],
query: {
keyword: this.$route.query.key,
pageNum: 1,
pageSize: 10,
total: 0
}
}
},
created() {
this.fetchList()
},
methods: {
fetchList() {
searchByKeyword(this.query).then(value => {
const { data } = value
this.list = data.records
this.query.total = data.total
this.query.pageSize = data.size
this.query.pageNum = data.current
})
}
}
}
</script>
<style scoped>
</style>
复制代码
搜索后端实现
BmsSearchController
@RestController
@RequestMapping("/search")
public class BmsSearchController {
@Resource
private BmsPostService postService;
@GetMapping
public ApiResult<Page<PostVO>> searchList(@RequestParam("keyword") String keyword,
@RequestParam("pageNum") Integer pageNum,
@RequestParam("pageSize") Integer pageSize) {
Page<PostVO> results = postService.searchByKey(keyword, new Page<>(pageNum, pageSize));
return ApiResult.success(results);
}
}
复制代码
BmsPostService
public Page<PostVO> searchByKey(String keyword, Page<PostVO> page) {
// 查询话题
Page<PostVO> iPage = this.baseMapper.searchByKey(page, keyword);
return iPage;
}
复制代码
BmsPostMapper.xml
<select id="searchByKey" resultType="com.notepad.blog.domain.vo.PostVO">
SELECT t.id,
t.title,
t.user_id,
t.comments,
t.view,
t.collects,
t.top,
t.essence,
t.create_time,
t.modify_time,
u.username,
u.alias,
u.avatar
FROM bms_post t
LEFT JOIN ums_user u
ON t.user_id = u.id
<where>
<if test="keyword!=null">
and t.title like CONCAT('%','${keyword}')
or t.title like CONCAT('${keyword}','%')
or t.title like CONCAT('%','${keyword}','%')
or t.title = #{keyword}
</if>
</where>
order by t.view desc, t.create_time desc
</select>
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END