SpringBoot+React博客论坛系统 附带详细运行指导视频

一、项目演示

项目演示地址: 视频地址

二、项目介绍

项目描述:这是一个基于SpringBoot+React框架开发的博客论坛系统。首先,这是一个前后端分离的项目,文章编辑器支持Markdown语法,项目代码简洁规范,注释说明详细,易于理解和学习。其次,这项目功能丰富,具有一个博客论坛系统该有的所有功能。

项目功能:此项目分为两个角色:普通用户管理员普通用户有登录注册、浏览博客和问答信息、发表评论、问答发起者也能采纳评论、写文章、提问题、管理个人信息、关注他人等等功能。管理员除了拥有普通用户的所有功能,还有管理所有用户信息、管理所有文章信息、管理所有文章分类信息、管理所有文章标签信息、管理所有评论信息等等功能。

应用技术:SpringBoot + React + MySQL + MyBatis + Redis + Antd

运行环境:IntelliJ IDEA2019.3.5 + MySQL5.7(项目压缩包中自带) + Redis5.0.5(项目压缩包中自带) + JDK1.8 + Maven3.6.3(项目压缩包中自带)+ Node14.16.1(项目压缩包中自带)

三、项目运行截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、主要代码

1.前台编辑器页面代码:

 <div className={editorStyle.editor}>
     <div className={editorStyle.title}>
          <div className={editorStyle.back} onClick={() => backHome()}>
              返回首页
          </div>
          <div style={ 
        { 
        width: '80%', paddingTop: '0.5rem'}}>
              <Input defaultValue={article.title} value={article.title} onChange={ e => setArticle({...article, title: e.target.value}) } ref={inputTitle} className={editorStyle.input} placeholder="请在这里输入文章标题"/>
          </div>
      </div>
      <div className={editorStyle.content}>
          <EditorContent onSave={() => saveArticle(6, 1)} ref={editor} preview={true} subfield={true}
             addImg={($file) => addImg($file)}
             value={article.contentMarkdown} onChange={handleChange}/>
      </div>
      <div className={editorStyle.footer}>
          <div className={editorStyle.left}>
              <div style={ 
        { 
        width: '50%'}}>
                  <Select defaultValue={article.categoryId} value={article.categoryId} onChange={ e => setArticle({...article, categoryId: e}) }  style={
   
   {width: '100%'}} placeholder="请选择文章分类">
                      {
                          categoryList && categoryList.map((item, index) => {
                              return (
                                  <Select.Option key={index} value={item.id}>{item.name}</Select.Option>
                              )
                          })
                      }
                  </Select>
              </div>
              <div style={ 
        { 
        width: '50%', marginLeft: '1rem'}} >
                  <ConfigProvider locale={zhCN}>
                      <Select mode="multiple" defaultValue={article.tagList} value={article.tagList} onChange={ e => {
                          if(e.length > 3) {
                              message.warning("最多选择3个标签哦!")
                          } else {
                              setArticle({...article, tagList: e});
                          }
                      } } style={
   
   {width: '100%'}} placeholder="请选择文章标签">
                          {
                              tagList && tagList.map((item, index) => {
                                  return (
                                      <Select.Option key={index} value={item.id}>{item.name}</Select.Option>
                                  )
                              })
                          }
                      </Select>
                  </ConfigProvider>
              </div>

          </div>
          <div className={editorStyle.center}>
              <TextArea rows={1} defaultValue={article.summary} value={article.summary} onChange={ e => setArticle({...article, summary: e.target.value}) } placeholder="请输入文章摘要" />
          </div>
          <div className={editorStyle.right}>
              <div className={editorStyle.save} onClick={() => saveArticle(6, 1)}>
                  保存草稿箱
              </div>
              <div className={editorStyle.submit} onClick={() => saveArticle(1, 2)}>
                  发布
              </div>
          </div>
      </div>

  </div>

2.后端查询文章列表代码:

    /**
     * 分页获取文章数据
     * @param pageDTO
     * @return
     */
    @Override
    public ResponseDTO<PageDTO<ArticleDTO>> getArticleList(PageDTO<ArticleDTO> pageDTO) {
    
    
        ArticleExample articleExample = new ArticleExample();
        // 不知道当前页多少,默认为第一页
        if(pageDTO.getPage() == null){
    
    
            pageDTO.setPage(1);
        }
        // 不知道每页多少条记录,默认为每页5条记录
        if(pageDTO.getSize() == null){
    
    
            pageDTO.setSize(5);
        }
        ArticleExample.Criteria c1 = articleExample.createCriteria();
        if(pageDTO.getParam() != null) {
    
    
            ArticleDTO articleDTO = pageDTO.getParam();
            if(!CommonUtil.isEmpty(articleDTO.getCategoryId()) && !"0".equals(articleDTO.getCategoryId())) {
    
    
                c1.andCategoryIdEqualTo(articleDTO.getCategoryId());
            }
            if(!CommonUtil.isEmpty(articleDTO.getTitle())) {
    
    
                c1.andTitleLike("%" + articleDTO.getTitle() + "%");
            }
            if(articleDTO.getType() != null && articleDTO.getType() != 0) {
    
    
                c1.andTypeEqualTo(articleDTO.getType());
            }
            if(articleDTO.getState() != null && articleDTO.getState() != 0) {
    
    
                c1.andStateEqualTo(articleDTO.getState());
            }
            if(articleDTO.getState() == null) {
    
    
                List<Integer> stateList = new ArrayList<>();
                stateList.add(ArticleStateEnum.WAIT.getCode());
                stateList.add(ArticleStateEnum.DRAFT.getCode());
                stateList.add(ArticleStateEnum.FAIL.getCode());
                c1.andStateNotIn(stateList);
            }
            if(!CommonUtil.isEmpty(articleDTO.getUserId())
                    && !ArticleQueryTypeEnum.LIKE.getCode().equals(articleDTO.getQueryType())
                    && !ArticleQueryTypeEnum.COLLECT.getCode().equals(articleDTO.getQueryType())) {
    
    
                c1.andUserIdEqualTo(articleDTO.getUserId());
            }
            if(ArticleQueryTypeEnum.BLOG.getCode().equals(articleDTO.getQueryType())) {
    
    
                c1.andTypeEqualTo(ArticleTypeEnum.BLOG.getCode());
            }
            if(ArticleQueryTypeEnum.FORUM.getCode().equals(articleDTO.getQueryType())) {
    
    
                c1.andTypeEqualTo(ArticleTypeEnum.FORUM.getCode());
            }
            if(ArticleQueryTypeEnum.LIKE.getCode().equals(articleDTO.getQueryType())) {
    
    
                LikeExample likeExample = new LikeExample();
                likeExample.createCriteria().andUserIdEqualTo(articleDTO.getUserId());
                List<Like> likeList = likeMapper.selectByExample(likeExample);
                List<String> articleIdList = likeList.stream().map(Like::getArticleId).collect(Collectors.toList());
                if(articleIdList.size() == 0) {
    
    
                    articleIdList.add("-1");
                }
                c1.andIdIn(articleIdList);
            }
            if(ArticleQueryTypeEnum.COLLECT.getCode().equals(articleDTO.getQueryType())) {
    
    
                CollectExample collectExample = new CollectExample();
                collectExample.createCriteria().andUserIdEqualTo(articleDTO.getUserId());
                List<Collect> collectList = collectMapper.selectByExample(collectExample);
                List<String> articleIdList = collectList.stream().map(Collect::getArticleId).collect(Collectors.toList());
                if(articleIdList.size() == 0) {
    
    
                    articleIdList.add("-1");
                }
                c1.andIdIn(articleIdList);
            }
        }
        articleExample.setOrderByClause("top desc, essence desc, official desc, create_time desc");
        PageHelper.startPage(pageDTO.getPage(), pageDTO.getSize());
        // 分页查出文章数据
        List<Article> articleList = articleMapper.selectByExample(articleExample);
        PageInfo<Article> pageInfo = new PageInfo<>(articleList);
        // 获取数据的总数
        pageDTO.setTotal(pageInfo.getTotal());
        // 讲domain类型数据  转成 DTO类型数据
        List<ArticleDTO> articleDTOList = CopyUtil.copyList(articleList, ArticleDTO.class);
        for(ArticleDTO articleDTO : articleDTOList) {
    
    
            // 获取文章所属用户信息
            User user = userMapper.selectByPrimaryKey(articleDTO.getUserId());
            articleDTO.setUserDTO(CopyUtil.copy(user, UserDTO.class));
            // 获取文章所属标签信息
            TagItemExample tagItemExample = new TagItemExample();
            tagItemExample.createCriteria().andArticleIdEqualTo(articleDTO.getId());
            List<TagItem> tagItemList = tagItemMapper.selectByExample(tagItemExample);
            List<String> tagIdList = tagItemList.stream().map(TagItem::getTagId).collect(Collectors.toList());
            List<Tag> tagList;
            if(tagIdList.size() == 0) {
    
    
                tagList = new ArrayList<>();
            } else {
    
    
                TagExample tagExample = new TagExample();
                tagExample.createCriteria().andIdIn(tagIdList);
                tagList = tagMapper.selectByExample(tagExample);
            }
            articleDTO.setTagDTOList(CopyUtil.copyList(tagList, TagDTO.class));
            // 获取文章所属分类信息
            Category category = categoryMapper.selectByPrimaryKey(articleDTO.getCategoryId());
            if(category == null) {
    
    
                articleDTO.setCategoryDTO(CopyUtil.copy(new Category(), CategoryDTO.class));
            } else {
    
    
                articleDTO.setCategoryDTO(CopyUtil.copy(category, CategoryDTO.class));
            }
        }
        pageDTO.setList(articleDTOList);
        return ResponseDTO.success(pageDTO);
    }

猜你喜欢

转载自blog.csdn.net/dgfdhgghd/article/details/129230050
今日推荐