SpringBoot+Vue豆宝社区前后端分离项目手把手实战系列教程17---作者详情功能实现

204 阅读2分钟

豆宝社区项目实战教程简介

本项目实战教程配有免费视频教程,配套代码完全开源。手把手从零开始搭建一个目前应用最广泛的Springboot+Vue前后端分离多用户社区项目。本项目难度适中,为便于大家学习,每一集视频教程对应在Github上的每一次提交。

项目首页截图

image

代码开源地址

前端 后端

视频教程地址

视频教程

前端技术栈

Vue Vuex Vue Router Axios Bulma Buefy Element Vditor DarkReader

后端技术栈

Spring Boot Mysql Mybatis MyBatis-Plus Spring Security JWT Lombok

作者详情前端

API

src\api创建follow.js

  
import request from '@/utils/request'

// 关注
export function follow(id) {
  return request(({
    url: `/relationship/subscribe/${id}`,
    method: 'get'
  }))
}

// 取消关注
export function unFollow(id) {
  return request(({
    url: `/relationship/unsubscribe/${id}`,
    method: 'get'
  }))
}

// 验证是否关注
export function hasFollow(topicUserId) {
  return request(({
    url: `/relationship/validate/${topicUserId}`,
    method: 'get'
  }))
}

Author.vue

src\views\post\新增Author.vue

<template>
  <section id="author">
    <el-card class="" shadow="never">
      <div slot="header">
        <span class="has-text-weight-bold">👨‍💻 关于作者</span>
      </div>
      <div class="has-text-centered">
        <p class="is-size-5 mb-5">
          <router-link :to="{ path: `/member/${user.username}/home` }">
            {{ user.alias }} <span class="is-size-7 has-text-grey">{{ '@' + user.username }}</span>
          </router-link>
        </p>
        <div class="columns is-mobile">
          <div class="column is-half">
            <code>{{ user.topicCount }}</code>
            <p>文章</p>
          </div>
          <div class="column is-half">
            <code>{{ user.followerCount }}</code>
            <p>粉丝</p>
          </div>
        </div>
        <div>
          <button
            v-if="hasFollow"
            class="button is-success button-center is-fullwidth"
            @click="handleUnFollow(user.id)"
          >
            已关注
          </button>

          <button v-else class="button is-link button-center is-fullwidth" @click="handleFollow(user.id)">
            关注
          </button>
        </div>
      </div>
    </el-card>
  </section>
</template>

<script>
import { follow, hasFollow, unFollow } from '@/api/follow'
import { mapGetters } from 'vuex'
export default {
  name: 'Author',
  props: {
    user: {
      type: Object,
      default: null
    }
  },
  data() {
    return {
      hasFollow: false
    }
  },
  mounted() {
    this.fetchInfo()
  },
  computed: {
    ...mapGetters([
      'token'
    ])
  },
  methods: {
    fetchInfo() {
      if(this.token != null && this.token !== '')
      {
        hasFollow(this.user.id).then(value => {
          const { data } = value
          this.hasFollow = data.hasFollow
        })
      }
    },
    handleFollow: function(id) {
      if(this.token != null && this.token !== '')
      {
        follow(id).then(response => {
          const { message } = response
          this.$message.success(message)
          this.hasFollow = !this.hasFollow
          this.user.followerCount = parseInt(this.user.followerCount) + 1
        })
      }
      else{
        this.$message.success('请先登录')
      }
    },
    handleUnFollow: function(id) {
      unFollow(id).then(response => {
        const { message } = response
        this.$message.success(message)
        this.hasFollow = !this.hasFollow
        this.user.followerCount = parseInt(this.user.followerCount) - 1
      })
    }
  }
}
</script>

<style scoped>
</style>

修改Detail.vue

src\views\post\Detail.vue

image-20210213195359737

作者详情后端

BmsFollowService

@Service
public class BmsFollowService extends ServiceImpl<BmsFollowMapper, BmsFollow> {
}

BmsFollowController

package com.notepad.blog.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.notepad.blog.common.api.ApiResult;
import com.notepad.blog.common.exception.ApiAsserts;
import com.notepad.blog.domain.BmsFollow;
import com.notepad.blog.domain.UmsUser;
import com.notepad.blog.service.BmsFollowService;
import com.notepad.blog.service.UmsUserService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName BmsFollowMapper
 * @description:
 * @author: 一粒麦子
 * @Date 2021/2/13 20:00
 **/
@RestController
@RequestMapping("/relationship")
public class BmsFollowController{

    @Resource
    private BmsFollowService bmsFollowService;

    @Resource
    private UmsUserService umsUserService;

    /**
     * 关注
     * @param userName
     * @param parentId
     * @return
     */
    @GetMapping("/subscribe/{userId}")
    public ApiResult<Object> handleFollow(
            @RequestHeader(value = "userName") String userName
            , @PathVariable("userId") String parentId) {

        UmsUser umsUser = umsUserService.getOne(new LambdaQueryWrapper<UmsUser>().eq(UmsUser::getUsername,userName));

        if (parentId.equals(umsUser.getId())) {
            ApiAsserts.fail("您脸皮太厚了,怎么可以关注自己呢 😮");
        }
        BmsFollow one = bmsFollowService.getOne(
                new LambdaQueryWrapper<BmsFollow>()
                        .eq(BmsFollow::getParentId, parentId)
                        .eq(BmsFollow::getFollowerId, umsUser.getId()));
        if (!ObjectUtils.isEmpty(one)) {
            ApiAsserts.fail("已关注");
        }

        BmsFollow follow = new BmsFollow();
        follow.setParentId(parentId);
        follow.setFollowerId(umsUser.getId());
        bmsFollowService.save(follow);
        return ApiResult.success(null, "关注成功");
    }

    /**
     * 取消关注
     * @param userName
     * @param parentId
     * @return
     */
    @GetMapping("/unsubscribe/{userId}")
    public ApiResult<Object> handleUnFollow(@RequestHeader(value = "userName") String userName
            , @PathVariable("userId") String parentId) {

        UmsUser umsUser = umsUserService.getOne(new LambdaQueryWrapper<UmsUser>().eq(UmsUser::getUsername,userName));

        BmsFollow one = bmsFollowService.getOne(
                new LambdaQueryWrapper<BmsFollow>()
                        .eq(BmsFollow::getParentId, parentId)
                        .eq(BmsFollow::getFollowerId, umsUser.getId()));
        if (ObjectUtils.isEmpty(one)) {
            ApiAsserts.fail("未关注!");
        }
        bmsFollowService.remove(new LambdaQueryWrapper<BmsFollow>().eq(BmsFollow::getParentId, parentId)
                .eq(BmsFollow::getFollowerId, umsUser.getId()));
        return ApiResult.success(null, "成功取消关注");
    }

    /**
     * 验证是否关注
     * @param userName
     * @param topicUserId
     * @return
     */
    @GetMapping("/validate/{topicUserId}")
    public ApiResult<Map<String, Object>> isFollow(@RequestHeader(value = "userName") String userName
            , @PathVariable("topicUserId") String topicUserId) {

        UmsUser umsUser = umsUserService.getOne(new LambdaQueryWrapper<UmsUser>().eq(UmsUser::getUsername,userName));

        Map<String, Object> map = new HashMap<>(16);
        map.put("hasFollow", false);
        if (!ObjectUtils.isEmpty(umsUser)) {
            BmsFollow one = bmsFollowService.getOne(new LambdaQueryWrapper<BmsFollow>()
                    .eq(BmsFollow::getParentId, topicUserId)
                    .eq(BmsFollow::getFollowerId, umsUser.getId()));
            if (!ObjectUtils.isEmpty(one)) {
                map.put("hasFollow", true);
            }
        }
        return ApiResult.success(map);
    }

}