Bean Treasure community project actual combat tutorial introduction

This project is equipped with a free video tutorial, the supporting code is completely open source. Build from scratch the most widely used Springboot+Vue front-end and back-end separation multi-user community project. This project is of moderate difficulty. For your convenience, each video tutorial will correspond to each submission on Github.

Screenshot of project Home Page

Open source code address

The front end

Video Tutorial Address

Video tutorial

Front-end technology stack

Vue Vuex Vue Router Axios Bulma Buefy Element Vditor DarkReader

Back-end technology stack

Spring Boot Mysql Mybatis MyBatis-Plus Spring Security JWT Lombok

Search front end implementation

API

The SRC \ API \ new search js

import request from '@/utils/request'

// Keyword search
export function searchByKeyword(query) {
  return request({
    url: `/search`.method: 'get'.params: {
      keyword: query.keyword,
      pageNum: query.pageNum,
      pageSize: query.pageSize
    }
  })
}
Copy the code

routing

src\router\index.js

./ / search
  {
    name: 'search'.path: '/search'.component: () = > import('@/views/Search'),
    meta: { title: 'retrieve'}}Copy the code

The new Search. Vue

src/views/Search

<template> <div> <el-card shadow="never"> <div slot="header" class="clearfix"> Retrieve <code>{{list.length}}</code> about <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. The username} / home `} "> {{item. Alias}} < / router - the link > < span class =" Mr - 1 "> published in: {{ 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: The tag. The name}} "> {{" #" + tag. The name}} < / router - the link > < / span > < span class = "is hidden - mobile" > browse: {{item. View}} < / span > </div> </div> </nav> </div> <div class="media-right" /> </article> </div> <! -- pagination --> <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>Copy the code

Search for back-end implementations

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));
        returnApiResult.success(results); }}Copy the code

BmsPostService

   public Page<PostVO> searchByKey(String keyword, Page<PostVO> page) {
        // Query the topic
        Page<PostVO> iPage = this.baseMapper.searchByKey(page, keyword);
        return iPage;
    }
Copy the code

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>
Copy the code