Spring Boot + vue-element 开发个人博客项目实战教程(二十八、保存草稿功能)

86 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

这里需要修改一下文章的数据库,有一些字段需要修改,多的字段暂时就不删除了,不然就改动的很多。

DROP TABLE IF EXISTS `person_article`;
CREATE TABLE `person_article` (
  `id`             INT             NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
  `author`         VARCHAR(128)    NOT NULL                            COMMENT '作者',
  `title`          VARCHAR(255)    NOT NULL                            COMMENT '文章标题',
	`user_id`        INT(11)         NOT NULL                            COMMENT '用户id',
	`category_id`    INT(11)             NULL                            COMMENT '分类id',
	`content`        LONGTEXT        NOT NULL                            COMMENT '文章内容',
  `views`          BIGINT          NOT NULL DEFAULT 0                  COMMENT '文章浏览量',
	`total_words`    BIGINT          NOT NULL DEFAULT 0                  COMMENT '文章总字数',
  `commentable_id` INT    		         NULL                            COMMENT '评论id',
	`art_status`     TINYINT    	   NOT NULL DEFAULT 1                  COMMENT '发布,默认1, 1-发布, 2-仅我可见  3-草稿',
	`description`    VARCHAR(255)        NULL                            COMMENT '描述',
	`image_url`      VARCHAR(255)        NULL                            COMMENT '文章logo',
  `create_time`    DATETIME            NULL DEFAULT CURRENT_TIMESTAMP  COMMENT '创建时间',
  `update_time`    DATETIME            NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间'
) ENGINE = InnoDB
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_bin
  ROW_FORMAT = Dynamic
  COMMENT '文章管理表';

还有文章和标签的关联表数据库也要修改一下,把表的id删除掉,这个字段多余的。

DROP TABLE IF EXISTS `person_article_tag`;
CREATE TABLE `person_article_tag` (
    `tag_id`		INT(11)           NOT NULL              COMMENT '标签id',
    `article_id`	INT(11)         NOT NULL              COMMENT '文章id'
) ENGINE = InnoDB
  CHARACTER SET = utf8mb4
  COLLATE = utf8mb4_bin
  ROW_FORMAT = Dynamic
  COMMENT '文章和标签关联表';

相对应的实体类和xml这两个文件要把id删除掉,这里我就不展示了,只删除id即可。

保存草稿功能相对于保存文章比较简单,不需要进入到弹出框之前就结束了这个功能,先找到我们之前写的保存草稿页面,点击功能需要完善即可。这里就修改了一下点击的方法名称。

<el-button type="warning" 
      size="medium" 
      @click="saveDraft" 
      style="margin-left:10px" 
      v-if="article.id === '' || article.artStatus == 3"
>保存草稿</el-button>

接下来我们来实现saveDraft方法的功能。

saveDraft() {
      this.article.artStatus = 3;
      if (this.article.title.trim() == "") {
        this.$message.error("文章标题不能为空");
        return false;
      }
      if (this.article.content.trim() == "") {
        this.$message.error("文章内容不能为空");
        return false;
      }
      var body = this.article;
      addArticle(body).then(res => {
        if(res.code === 200) {
          this.$message({
            type: 'success',
            message: '保存草稿成功!'
          });
        } else {
          this.$message({
            type: 'error',
            message: '保存草稿失败!'
          });
        }
      })
},

从以上代码可以看出,我先校验了文章的标题和内容,然后调用了添加文章的接口进行文章保存。

这里还要修改一下文章保存的接口,我们之前设计的不太合理,现在需要再完善一下。

首先添加一个文章保存的对象:ArticleInsertBO.java

package com.blog.personalblog.bo;

import lombok.Data;

/**
 * @author: SuperMan
 * @create: 2022-10-02
 */

@Data
public class ArticleInsertBO {
    /**
     * 文章id
     */
    private Integer id;

    /**
     * 文章标题
     */
    private String title;

    /**
     * 分类id
     */
    private Integer categoryId;

    /**
     * 文章内容
     */
    private String content;

    /**
     * 发布,默认1, 1-发布, 2-仅我可见  3-草稿
     */
    private Integer artStatus;

    /**
     * 描述
     */
    private String description;

    /**
     * 文章logo
     */
    private String imageUrl;

    /**
     * 分类名称
     */
    private String categoryName;

     /**
     * 文章标签
     */
    private List<String> tagNameList;
}

然后修改接口,这里我将修改个添加整合到一个接口中,可以减少重复的代码

	/**
     * 新建文章
     * @param bo
     * @return
     */
    void insertOrUpdateArticle(ArticleInsertBO bo);

分类还要新加一个根据分类名称查询分类的接口以及实现方法,我这里就直接把代码列出来,相信大家对这操作也都比较熟练了。

	/**
     * 获取分类
     * @param categoryName
     * @return
     */
    Category getCategoryByName(String categoryName);
    @Override
    public Category getCategoryByName(String categoryName) {
        Category category = categoryMapper.getCategoryByName(categoryName);
        return category;
    }

CategoryMapper.java:

Category getCategoryByName(String categoryName);
<select id="getCategoryByName" resultType="com.blog.personalblog.entity.Category">
    select * from person_category where category_name = #{categoryName, jdbcType=VARCHAR}
</select>

再将文章的发布形式单独提出来,写成一个枚举类,方便以后维护。

package com.blog.personalblog.common;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * @author: SuperMan
 * @create: 2022-10-10
 **/

@Getter
@AllArgsConstructor
public enum ArticleArtStatusEnum {
    /**
     * 发布
     */
    PUBLISH(1, "发布"),
    /**
     * 仅我可见
     */
    ONLYME(2, "仅我可见"),
    /**
     * 草稿
     */
    DRAFT(3, "草稿");

    /**
     * 状态
     */
    private final Integer status;

    /**
     * 描述
     */
    private final String desc;
}

然后我们来写文章保存或修改的实现类。

这一块的逻辑相比较之前的有了一些变化,希望大家好好看一下这个逻辑,如果看不明白可以留言,我这里不再讲述了。

    @Resource
    private CategoryService categoryService;
    @Resource
    private UserService userService;


    @Override
    public void insertOrUpdateArticle(ArticleInsertBO bo) {
        //分类添加
        Category category = saveCategory(bo);
        Article article = BeanUtil.copyProperties(bo, Article.class);
        if (category != null) {
            article.setCategoryId(category.getCategoryId());
        }
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        User user = userService.getUserByUserName(username);
        article.setUserId(user.getId());
        article.setAuthor(user.getUserName());
		article.setViews(0L);
        article.setTotalWords(0L);
        if (bo.getId() != null) {
            articleMapper.updateArticle(article);
        } else {
            articleMapper.createArticle(article);
        }
        articleMap.put(article.getId(), article);
        //添加文章标签
        saveTags(bo, article.getId());

        //添加文章发送邮箱提醒
        try {
            String content = "【{0}】您好:\n" +
                    "您已成功发布了标题为: {1} 的文章 \n" +
                    "请注意查收!\n";
            MailInfo build = MailInfo.builder()
                    .receiveMail(user.getEmail())
                    .content(MessageFormat.format(content, user.getUserName(), article.getTitle()))
                    .title("文章发布")
                    .build();
            SendMailConfig.sendMail(build);
        } catch (Exception e) {
            log.error("邮件发送失败{}", e.getMessage());
        }

    }

    private Category saveCategory(ArticleInsertBO bo) {
        if (StrUtil.isEmpty(bo.getCategoryName())) {
            return null;
        }
        Category category = categoryService.getCategoryByName(bo.getCategoryName());
        if (category == null && !ArticleArtStatusEnum.DRAFT.getStatus().equals(bo.getArtStatus())) {
            category.setCategoryName(bo.getCategoryName());
            categoryService.saveCategory(category);
        }
        return category;
    }

    private void saveTags(ArticleInsertBO bo, Integer articleId) {
        //首先判断是不是更新文章
        if (bo.getId() == null) {
            articleTagService.deleteTag(bo.getId());
        }
        //添加文章标签
        List<String> tagNameList = bo.getTagNameList();
        List<Integer> tagIdList = new ArrayList<>();

        if (CollUtil.isNotEmpty(tagNameList)) {
            //先查看添加的标签数据库里有没有
            for (String tagName : tagNameList) {
                Tag one = tagService.findByTagName(tagName);
                if (one == null) {
                    Tag tag = new Tag();
                    tag.setTagName(tagName);
                    tagService.saveTag(tag);
                    tagIdList.add(tag.getId());
                } else {
                    tagIdList.add(one.getId());
                }
            }
        }
        articleTagService.deleteTag(articleId);
        if (tagIdList != null) {
            List<ArticleTag> articleTagList = tagIdList.stream().map(tagId -> ArticleTag.builder()
                    .tagId(tagId)
                    .articleId(articleId)
                    .build()).collect(Collectors.toList());
            articleTagService.insertBatch(articleTagList);
        }
    }

好啦,后端修改完成了,别忘了文章的数据库表更新成最新修改的。接下来我们运行项目,启动后端项目,然后我们测试一下数据有没有成功。

显示操作成功了,说明接口是通的,然后我们再去看一下数据库有没有这条数据。

有数据,那我们的保存草稿功能就完成了。