原创

基于SpringBoot和Vue的个人博客系统,附源码

今天介绍一个博客项目,是基于SpringBoot和Vue的前后端分离项目,前台界面炫酷无比、科技感十足,后台管理端功能丰富。


项目特点

前台参考"Hexo"的"Butterfly"设计,美观简洁,响应式体验好。
后台参考"element-admin"设计,侧边栏,历史标签,面包屑自动生成。
采用Markdown编辑器,写法简单。
评论支持表情输入回复等,样式参考Valine。
添加音乐播放器,支持在线搜索歌曲。
前后端分离部署,适应当前潮流。
接入第三方登录,减少注册成本。
支持发布说说,随时分享趣事。
留言采用弹幕墙,更加炫酷。
支持代码高亮和复制,图片预览,深色模式等功能,提升用户体验。
搜索文章支持高亮分词,响应速度快。
新增文章目录、推荐文章等功能,优化用户体验。
新增在线聊天室,支持撤回、语音输入、统计未读数量等功能。
新增aop注解实现日志管理。
支持动态权限修改,采用RBAC模型,前端菜单和后台权限实时更新。
后台管理支持修改背景图片,博客配置等信息,操作简单,支持上传相册。
代码支持多种搜索模式(Elasticsearch或MYSQL),支持多种上传模式(OSS或本地),可支持配置。
代码遵循阿里巴巴开发规范,利于开发者学习。

技术介绍

前端: vue + vuex + vue-router + axios + vuetify + element + echarts

后端: SpringBoot + nginx + docker + SpringSecurity + Swagger2 + MyBatisPlus + Mysql + Redis + elasticsearch + RabbitMQ + MaxWell + Websocket

其他: 接入QQ,微博第三方登录,接入腾讯云人机验证、websocket

部分代码展示

<template>
  <div>
    <!-- banner -->
    <div class="home-banner" :style="cover">
      <div class="banner-container">
        <!-- 联系方式 -->
        <h1 class="blog-title animated zoomIn">
          {{ blogInfo.websiteConfig.websiteName }}
        </h1>
        <!-- 一言 -->
        <div class="blog-intro">
          {{ obj.output }} <span class="typed-cursor">|</span>
        </div>
        <!-- 联系方式 -->
        <div class="blog-contact">
          <a
            v-if="isShowSocial('qq')"
            class="mr-5 iconfont iconqq"
            target="_blank"
            :href="
              'http://wpa.qq.com/msgrd?v=3&uin=' +
                blogInfo.websiteConfig.qq +
                '&site=qq&menu=yes'
            "
          />
          <a
            v-if="isShowSocial('github')"
            target="_blank"
            :href="blogInfo.websiteConfig.github"
            class="mr-5 iconfont icongithub"
          />
          <a
            v-if="isShowSocial('gitee')"
            target="_blank"
            :href="blogInfo.websiteConfig.gitee"
            class="iconfont icongitee-fill-round"
          />
        </div>
      </div>
      <!-- 向下滚动 -->
      <div class="scroll-down" @click="scrollDown">
        <v-icon color="#fff" class="scroll-down-effects">
          mdi-chevron-down
        </v-icon>
      </div>
    </div>
    <!-- 主页文章 -->
    <v-row class="home-container">
      <v-col md="9" cols="12">
        <!-- 说说轮播 -->
        <v-card class="animated zoomIn" v-if="talkList.length > 0">
          <Swiper :list="talkList" />
        </v-card>
        <v-card
          class="animated zoomIn article-card"
          style="border-radius: 12px 8px 8px 12px"
          v-for="(item, index) of articleList"
          :key="item.id"
        >
          <!-- 文章封面图 -->
          <div :class="isRight(index)">
            <router-link :to="'/articles/' + item.id">
              <v-img
                class="on-hover"
                width="100%"
                height="100%"
                :src="item.articleCover"
              />
            </router-link>
          </div>
          <!-- 文章信息 -->
          <div class="article-wrapper">
            <div style="line-height:1.4">
              <router-link :to="'/articles/' + item.id">
                {{ item.articleTitle }}
              </router-link>
            </div>
            <div class="article-info">
              <!-- 是否置顶 -->
              <span v-if="item.isTop == 1">
                <span style="color:#ff7242">
                  <i class="iconfont iconzhiding" /> 置顶
                </span>
                <span class="separator">|</span>
              </span>
              <!-- 发表时间 -->
              <v-icon size="14">mdi-calendar-month-outline</v-icon>
              {{ item.createTime | date }}
              <span class="separator">|</span>
              <!-- 文章分类 -->
              <router-link :to="'/categories/' + item.categoryId">
                <v-icon size="14">mdi-inbox-full</v-icon>
                {{ item.categoryName }}
              </router-link>
              <span class="separator">|</span>
              <!-- 文章标签 -->
              <router-link
                style="display:inline-block"
                :to="'/tags/' + tag.id"
                class="mr-1"
                v-for="tag of item.tagDTOList"
                :key="tag.id"
              >
                <v-icon size="14">mdi-tag-multiple</v-icon>{{ tag.tagName }}
              </router-link>
            </div>
            <!-- 文章内容 -->
            <div class="article-content">
              {{ item.articleContent }}
            </div>
          </div>
        </v-card>
        <!-- 无限加载 -->
        <infinite-loading @infinite="infiniteHandler">
          <div slot="no-more" />
        </infinite-loading>
      </v-col>
      <!-- 博主信息 -->
      <v-col md="3" cols="12" class="d-md-block d-none">
        <div class="blog-wrapper">
          <v-card class="animated zoomIn blog-card mt-5">
            <div class="author-wrapper">
              <!-- 博主头像 -->
              <v-avatar size="110">
                <img
                  class="author-avatar"
                  :src="blogInfo.websiteConfig.websiteAvatar"
                />
              </v-avatar>
              <div style="font-size: 1.375rem;margin-top:0.625rem">
                {{ blogInfo.websiteConfig.websiteAuthor }}
              </div>
              <div style="font-size: 0.875rem;">
                {{ blogInfo.websiteConfig.websiteIntro }}
              </div>
            </div>
            <!-- 博客信息 -->
            <div class="blog-info-wrapper">
              <div class="blog-info-data">
                <router-link to="/archives">
                  <div style="font-size: 0.875rem">文章</div>
                  <div style="font-size: 1.25rem">
                    {{ blogInfo.articleCount }}
                  </div>
                </router-link>
              </div>
              <div class="blog-info-data">
                <router-link to="/categories">
                  <div style="font-size: 0.875rem">分类</div>
                  <div style="font-size: 1.25rem">
                    {{ blogInfo.categoryCount }}
                  </div>
                </router-link>
              </div>
              <div class="blog-info-data">
                <router-link to="/tags">
                  <div style="font-size: 0.875rem">标签</div>
                  <div style="font-size: 1.25rem">{{ blogInfo.tagCount }}</div>
                </router-link>
              </div>
            </div>
            <!-- 收藏按钮 -->
            <a class="collection-btn" @click="tip = true">
              <v-icon color="#fff" size="18" class="mr-1">mdi-bookmark</v-icon>
              加入书签
            </a>
            <!-- 社交信息 -->
            <div class="card-info-social">
              <a
                v-if="isShowSocial('qq')"
                class="mr-5 iconfont iconqq"
                target="_blank"
                :href="
                  'http://wpa.qq.com/msgrd?v=3&uin=' +
                    blogInfo.websiteConfig.qq +
                    '&site=qq&menu=yes'
                "
              />
              <a
                v-if="isShowSocial('github')"
                target="_blank"
                :href="blogInfo.websiteConfig.github"
                class="mr-5 iconfont icongithub"
              />
              <a
                v-if="isShowSocial('gitee')"
                target="_blank"
                :href="blogInfo.websiteConfig.gitee"
                class="iconfont icongitee-fill-round"
              />
            </div>
          </v-card>
          <!-- 网站信息 -->
          <v-card class="blog-card animated zoomIn mt-5 big">
            <div class="web-info-title">
              <v-icon size="18">mdi-bell</v-icon>
              公告
            </div>
            <div style="font-size:0.875rem">
              {{ blogInfo.websiteConfig.websiteNotice }}
            </div>
          </v-card>
          <!-- 网站信息 -->
          <v-card class="blog-card animated zoomIn mt-5">
            <div class="web-info-title">
              <v-icon size="18">mdi-chart-line</v-icon>
              网站资讯
            </div>
            <div class="web-info">
              <div style="padding:4px 0 0">
                运行时间:<span class="float-right">{{ time }}</span>
              </div>
              <div style="padding:4px 0 0">
                总访问量:<span class="float-right">
                  {{ blogInfo.viewsCount }}
                </span>
              </div>
            </div>
          </v-card>
        </div>
      </v-col>
    </v-row>
    <!-- 提示消息 -->
    <v-snackbar v-model="tip" top color="#49b1f5" :timeout="2000">
      按CTRL+D 键将本页加入书签
    </v-snackbar>
  </div>
</template>

演示视频链接

源码链接

正文到此结束
本文目录