基于Spring Boot+Vue的博客系统 17——点击分类或者标签跳转

废弃说明:
这个专栏的文章本意是记录笔者第一次搭建博客的过程,文章里里有很多地方的写法都不太恰当,现在已经废弃,关于SpringBoot + Vue 博客系列,笔者重新写了这个系列的文章,不敢说写的好,但是至少思路更加清晰,还在看SpringBoot + Vue 博客系列文章的朋友可以移步:https://blog.csdn.net/li3455277925/category_10341110.html,文章中有错误的地方或者大家有什么意见或建议都可以评论或者私信交流。

需求

在主页有两个面板分别是展示所有标签的面板和展示所有分类的面板,这里需要实现这两个面板,并且点击这两个面板上的链接可以更新articles.vue组件中的文章数据。

实现

后端api设计

主要涉及到四个api,分别是:获取所有标签、获取所有分类、根据标签获取文章,根据分类获取文章
Controller的设计如下:

@GetMapping("/getCategories")
public List<Map<String, Object>> getCategories() {
    List<Map<String, Object>> categories = articleService.findAllCategories();
    return categories;
}

@GetMapping("/getTags")
public Set<String> getTags() {
    Set<String> tags = articleService.findAllTags();
    return tags;
}

@GetMapping("/getArticlesByTag")
public PageInfoVO<SimpleArticleVO> pageArticlesByTag(String tag, @RequestParam(name = "pageNumber", required = false, defaultValue = "1") Integer pageNumber) {
    PageInfoVO<SimpleArticleVO> pageInfoVO = articleService.pageArticleByTag(tag, pageNumber);
    return pageInfoVO;
}

@GetMapping("/getArticlesByCategory")
public PageInfoVO<SimpleArticleVO> pageArticlesByCategory(String category, @RequestParam(name = "pageNumber", required = false, defaultValue = "1") Integer pageNumber) {
    PageInfoVO<SimpleArticleVO> pageInfoVO = articleService.pageArticlesByCategory(category, pageNumber);
    return pageInfoVO;
}

业务代码:

/**
 * 查询所有文章分类,并且统计每种分类的文章数目,这里数据访问层返回的map集合中键都为大写字母,这里将其转换为小写字母
 *
 * @return
 */
public List<Map<String, Object>> findAllCategories() {
    List<Map<String, Object>> maps = new ArrayList<>();
    List<Map<String, Object>> categories = articleRepository.findAllCategories();
    categories.forEach(map -> {
        Map<String, Object> stringObjectMap = new HashMap<>();
        map.forEach((k, v) -> stringObjectMap.put(k.toLowerCase(), v));
        maps.add(stringObjectMap);
    });
    return maps;
}

/**
 * 获取所有标签
 *
 * @return
 */
public Set<String> findAllTags() {
    // 使用Set去重
    List<String> allTags = articleRepository.findAllTags();
    Set<String> resList = new HashSet<>();
    allTags.forEach(tag -> {
        String[] strings = tag.split(",");
        Collections.addAll(resList, strings);
    });
    return resList;
}

/**
 * 根据标签查询文章信息
 *
 * @param tag
 * @param pageNumber
 * @return
 */
public PageInfoVO<SimpleArticleVO> pageArticleByTag(String tag, Integer pageNumber) {

    // 增加容错
    pageNumber = pageNumber < 1 ? 0 : pageNumber - 1;
    Pageable pageable = new PageRequest(pageNumber, PAGE_SIZE, GMT_UPDATE_DESC_SORT);
    Page<ArticleDO> page = articleRepository.findArticlesByTagsLike("%" + tag + "%", pageable);
    List<ArticleDO> items = page.getContent();
    ArrayList<SimpleArticleVO> res = ArticleUtil.jpaDosToSimpleArticleVOs(items);

    PageInfoVO<SimpleArticleVO> pageInfoVO = new PageInfoVO<>();
    pageInfoVO.setTotalPages(page.getTotalPages());
    pageInfoVO.setTotalCount(page.getTotalElements());
    pageInfoVO.setCurrentPage(pageNumber + 1);
    pageInfoVO.setData(res);
    return pageInfoVO;
}

/**
 * 根据分类查询文章信息
 *
 * @param category
 * @param pageNumber
 * @return
 */
public PageInfoVO<SimpleArticleVO> pageArticlesByCategory(String category, Integer pageNumber) {
    // 增加容错
    pageNumber = pageNumber < 1 ? 0 : pageNumber - 1;
    Pageable pageable = new PageRequest(pageNumber, PAGE_SIZE, GMT_UPDATE_DESC_SORT);
    Page<ArticleDO> page = articleRepository.findArticlesByCategory(category, pageable);

    PageInfoVO<SimpleArticleVO> pageInfoVO = new PageInfoVO<>();
    pageInfoVO.setData(ArticleUtil.jpaDosToSimpleArticleVOs(page.getContent()));
    pageInfoVO.setCurrentPage(pageNumber + 1);
    pageInfoVO.setTotalCount(page.getTotalElements());
    pageInfoVO.setTotalPages(page.getTotalPages());
    return pageInfoVO;
}

数据库访问层ArticleRepository代码:

// 只查询一个字段,网上的重写构造器、重新定义接口的实现方法太麻烦了
@Query(value = "select category,count(1) as number from article group by category", nativeQuery = true)
List<Map<String, Object>> findAllCategories();

@Query(value = "select distinct tags from article", nativeQuery = true)
List<String> findAllTags();

Page<ArticleDO> findArticlesByTagsLike(String tag, Pageable pageable);

Page<ArticleDO> findArticlesByCategory(String category, Pageable pageable);
前端页面

/src/request/api/url.js中添加对应的URL

const getCategoriesUrl = baseUrl + 'api/comm/article/getCategories';
const getTagsUrl = baseUrl + 'api/comm/article/getTags';
const getArticlesByTagUrl = baseUrl + 'api/comm/article/getArticlesByTag';
const getArticlesByCategoryUrl = baseUrl + 'api/comm/article/getArticlesByCategory';

/src/request/api/article.js里面封装请求方法

getArticles(callback) {
  let pageInfo = store.state.articles;
  if (pageInfo.condition) {
    switch (pageInfo.condition) {
      case 'all':
        this.getPageArticles(pageInfo.currentPage, callback);
        break;
      case 'tag':
        this.getArticlesByTag(pageInfo.tag, pageInfo.currentPage, callback);
        break;
      case 'category':
        this.getArticlesByCategory(pageInfo.category, pageInfo.currentPage, callback);
        break;
      case 'queryString':
        this.getArticlesByQueryString(pageInfo.queryString, pageInfo.currentPage, callback);
        break;
    }
  }
},
getCategories(callback) {
  axios
    .get(url.getCategoriesUrl)
    .then(callback)
    .catch(err => {
      console.log("getCategories Error");
    });
},
getTags(callback) {
  axios
    .get(url.getTagsUrl)
    .then(callback)
    .catch(err => {
      console.log("getTags Error");
    });
},
getArticlesByTag(tag, pageNumber, callback) {
  axios
    .get(url.getArticlesByTagUrl, {
      params: {
        tag: tag,
        pageNumber: pageNumber
      }
    })
    .then(callback)
    .catch(err => {
      console.log("getArticlesByTag Error");
    });
},
getArticlesByCategory(category, pageNumber, callback) {
  axios
    .get(url.getArticlesByCategoryUrl, {
      params: {
        category: category,
        pageNumber: pageNumber
      }
    })
    .then(callback)
    .catch(err => {
      console.log("getArticlesByCategory Error");
    });
},

在组件articleKinds.vuetags.vue里面调用请求方法获取数据,渲染到页面

<template>
  <b-card border-variant="light" header="文章分类" align="left" class="main">
    <b-card-text v-for="(c, index) in categories" :key="index">
      <b-link @click="getArticlesByCategory(c.category)">{{c.category}}</b-link>
      <b-badge variant="light" class="float-right">{{c.number}}篇</b-badge>
    </b-card-text>
  </b-card>
</template>

<script>
import { mapMutations } from "vuex";
export default {
  name: "articleKinds",
  data() {
    return {
      categories: null
    };
  },
  methods: {
    ...mapMutations(["setPageInfo", "setCurrentPage", "setCondition"]),
    getArticlesByCategory(category) {
      this.setCondition({
        condition: "category",
        info: category
      });
      this.setCurrentPage(1);
      this.$api.article.getArticles(resp => {
        this.setPageInfo(resp.data);
      });
    }
  },
  created() {
    this.$api.article.getCategories(resp => {
      this.categories = resp.data;
    });
  }
};
</script>

<style scoped>
.main {
  margin-top: 10px;
}
.float-right {
  float: right;
}
</style>
<template>
  <b-card border-variant="light" header="全部标签" align="left" class="main">
    <b-link
      @click="getArticlesByTag(tag)"
      v-for="(tag,index) in tags"
      :key="index"
      class="link-icon"
    >
      <i class="icon iconfont icon-tag"></i>
      {{tag}}
    </b-link>
  </b-card>
</template>

<script>
import { mapMutations } from "vuex";
export default {
  name: "tags",
  data() {
    return {
      tags: null
    };
  },
  methods: {
    ...mapMutations(["setPageInfo", "setCurrentPage", "setCondition"]),
    getArticlesByTag(tag) {
      this.setCondition({
        condition: "tag",
        info: tag
      });
      this.setCurrentPage(1);
      this.$api.article.getArticles(resp => {
        this.setPageInfo(resp.data);
      });
    }
  },
  created() {
    this.$api.article.getTags(resp => {
      this.tags = resp.data;
    });
  }
};
</script>
<style scoped>
.main {
  margin-top: 10px;
}

.link-icon {
  text-decoration: none;
  display: inline-block;
  margin: 4px 10px;
}
</style>
页面效果

页面效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值