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

Paging front-end

1. The SRC \ components to create Pagination \ index vue

<template> <div :class="{ hidden: hidden }" class="pagination-container"> <el-pagination :background="background" :current-page.sync="currentPage" :page-size.sync="pageSize" :layout="layout" :page-sizes="pageSizes" :total="total" v-bind="$attrs" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </div> </template> <script> import {scrollTo} from "@/utils/scroll-to"; export default { name: "Pagination", props: { total: { required: true, type: Number, }, page: { type: Number, default: 1, }, limit: { type: Number, default: 10, }, pageSizes: { type: Array, default() { return [5, 10, 20, 30, 50]; }, }, layout: { type: String, default: "total, sizes, prev, pager, next, jumper", // default: 'sizes, prev, pager, next, jumper' }, background: { type: Boolean, default: true, }, autoScroll: { type: Boolean, default: true, }, hidden: { type: Boolean, default: false, }, }, computed: { currentPage: { get() { return this.page; }, set(val) { this.$emit("update:page", val); }, }, pageSize: { get() { return this.limit; }, set(val) { this.$emit("update:limit", val); }, }, }, methods: { handleSizeChange(val) { this.$emit("pagination", { page: this.currentPage, limit: val }); if (this.autoScroll) { scrollTo(0, 800); } }, handleCurrentChange(val) { this.$emit("pagination", { page: val, limit: this.pageSize }); if (this.autoScroll) { scrollTo(0, 800); ,}}}}; </script> <style scoped> .pagination-container { /* background: #fff; */ padding: 5px 0px; } .pagination-container.hidden { display: none; } </style>Copy the code

2. SRC \ utils to create scroll – to. Js

Math.easeInOutQuad = function(t, b, c, d) {
    t /= d / 2
    if (t < 1) {
      return c / 2 * t * t + b
    }
    t--
    return -c / 2 * (t * (t - 2) - 1) + b
  }
  
  // requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
  var requestAnimFrame = (function() {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60)}}) ()/**
   * Because it's so fucking difficult to detect the scrolling element, just move them all
   * @param {number} amount* /
  function move(amount) {
    document.documentElement.scrollTop = amount
    document.body.parentNode.scrollTop = amount
    document.body.scrollTop = amount
  }
  
  function position() {
    return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
  }
  
  / * * *@param {number} to
   * @param {number} duration
   * @param {Function} callback* /
  export function scrollTo(to, duration, callback) {
    const start = position()
    const change = to - start
    const increment = 20
    let currentTime = 0
    duration = (typeof (duration) === 'undefined')?500 : duration
    var animateScroll = function() {
      // increment the time
      currentTime += increment
      // find the value with the quadratic in-out easing function
      var val = Math.easeInOutQuad(currentTime, start, change, duration)
      // move the document.body
      move(val)
      // do the animation unless its over
      if (currentTime < duration) {
        requestAnimFrame(animateScroll)
      } else {
        if (callback && typeof (callback) === 'function') {
          // the animation is done so lets callback
          callback()
        }
      }
    }
    animateScroll()
  }
Copy the code

3. Modify the SRC \ views \ post \ index vue

Here’s what index.vue is all about

<template> <div> <el-card shadow="never"> <div slot="header" class="clearfix"> <el-tabs v-model="activeName" @tab-click="handleClick"> <el-tab-pane label=" latest theme "name="latest"> <article v-for="(item, index) in articleList" :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`" style="border-radius: 5px;" > </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 > < / el - TAB - pane > < el - TAB - pane label = "hot topics" name = "hot" > <article v-for="(item, index) in articleList" :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`" style="border-radius: 5px;" > </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 > < / el - TAB - pane > < el - TAB - pane label = "recent changes" name="update"> <article v-for="(item, index) in articleList" :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`" style="border-radius: 5px;" > </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> </el-tab-pane> </el-tabs> </div> <! <pagination v-show="page.total > 0" :total="page.total" :page.sync="page.current" :limit. Sync ="page.size" @pagination="init" /> </el-card> </div> </template> <script> import { getList } from '@/api/post' import Pagination from  '@/components/Pagination' export default { name: 'TopicList', components: { Pagination }, data() { return { activeName: 'latest', articleList: [], page: { current: 1, size: 10, total: 0, tab: 'latest' } } }, created() { this.init(this.tab) }, methods: { init(tab) { getList(this.page.current, this.page.size, tab).then((response) => { const { data } = response this.page.current = data.current this.page.total = data.total this.page.size = data.size this.articleList = data.records }) }, handleClick(tab) { this.init(tab.name) } } } </script> <style scoped> </style>Copy the code

4. Test questions

The test page has not been paginated, and needs to be displayed after pagination

Paging backend

MybatisPlusConfig

@Configuration
public class MybatisPlusConfig {

    MybatisConfiguration#useDeprecatedExecutor = false to avoid cache problems (this property will be removed when the old plugin is removed) */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(a) {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer(a) {
        return configuration -> configuration.setUseDeprecatedExecutor(false); }}Copy the code

The test page