写点什么

从零到一搭建一个属于自己的博客系统 (弍)

作者:木偶
  • 2022-10-24
    陕西
  • 本文字数:8773 字

    阅读完需:约 29 分钟

从零到一搭建一个属于自己的博客系统(弍)

前言:在上篇博客从零到一搭建一个属于自己的博客系统(弌)中我们讲到了登录界面以及功能的实现,接下来我们来看看首页制作以及文章的发布




  1. 环境:vue+webpack

  2. 请求的发送:axios

  3. 后端接口:Django

  4. 数据库:mysql<br>

项目结构图:



(- - -在上篇文章中,我们少了很多的细节,接下来这篇博文中我会来给大家补上的哦- - -)

一.路由守护:



我们深知,必须登录之后才可以进行页面之间的的跳转访问,也就是路由的相互跳转,但是我们上一篇文章中却疏忽了这一点,这次来补上(详情请移步:Vue中进行全局守卫):


 this.$get('/login').then(res => {          var a = ''          var b = ''          console.log(res)          for (var i = 0; i < res.length; i++) {            if (this.user === res[i][0] && this.pwd === res[i][1]) {              a = res[i][0]              b = res[i][1]              this.time = this.timestampToTime(Date.now() / 1000)              sessionStorage.setItem('sid', '已登录') // 设置本地存储信息              sessionStorage.setItem('user', this.user) // 设置本地存储信息              sessionStorage.setItem('time', this.time) // 设置本地存储信息              this.$message({                message: '恭喜你,登录成功!',                type: 'success'              })              this.$router.push({                name: 'homepage'              })            }
复制代码


在我们登录成功时候向session中插入我们需要的信息,如下图:



进行了信息的存储也提示了我们登录成功的消息,并且进行了页面之间的跳转。


接下来我们在main.js中进行以下配置:


// 全局守卫router.beforeEach((to, from, next) => {  // 获取登陆状态  let isLogin = sessionStorage.getItem('sid')  if (to.name === 'login') { // 如果是登录页,则跳过验证    next()    return  }  if (!isLogin) { //  判断登陆状态,sessionStorage不存在的情况下    ElementUI.Message({      message: '请先登录系统',      type: 'error'    })    next({      name: 'login'    }) // 如果未登录,则跳转到登录页  } else {    next() // 如果已经登陆,那就可以跳转  }})
复制代码


这样子就只有登录了才能进入我们的系统哦~~~~



二.axios 封装:

发送请求肯定不止止是一个,那么我们可以进行 axios 的封装,有利于我们更好的发送请求(Vue中进行对于axios的封装):



三.Homepage(首页):

既然登录成功了,那么肯定有个目标页,我们一起来看看首页:



(有可能会有点丑,但是还得大家多多包涵俺的设计水平 ^_^ )

1.需求:

  • 个人的信息以及登录时间;

  • 切换账号和退出登录;

  • 可以进行的操作(发布文章、个人中心、点赞、评论);

  • 博文数据的显示;



2.HTML 代码:

明白需求那么开始进行页面的设计:


<template>  <div class="homepage">    <el-container>      <el-header>        <!-- 头部样式 -->        <div class="head">          <div class="head-center">            <span style="font-weight: 600;font-size:18px;float: left;">欢迎您:{{text}} | 登录时间:{{time}}</span>            <span class="span_text" @click="exit"> 退出登录 </span>            <span style="float:right">&nbsp;<em>|</em>&nbsp;</span>            <span class="span_text" @click="exit">切换账号</span>            <div style="float:right">              <el-dropdown>                <div class='img el-dropdown-link'>                  <el-avatar src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"></el-avatar>                </div>                <el-dropdown-menu slot="dropdown">                  <el-dropdown-item icon="el-icon-edit" @click.native='bumittext()'>发布文章</el-dropdown-item>                  <el-dropdown-item icon="el-icon-user-solid">个人中心</el-dropdown-item>                  <el-dropdown-item icon="el-icon-plus">点赞</el-dropdown-item>                  <el-dropdown-item icon="el-icon-circle-plus">评论</el-dropdown-item>                </el-dropdown-menu>              </el-dropdown>            </div>          </div>        </div>      </el-header>      <!-- 中心内容 -->      <el-main>        <div class="content-text" v-for='(item,index) in data'>          <!-- 标题 -->          <div class="content-title">            <strong> {{item[2]}}</strong>          </div>          <!-- 中心内容缩略显示 -->          <div class="content-center">            <p>{{item[3]}}</p>          </div>          <!-- 点赞,评论 -->          <div class="content-dzpl">            <span style="margin-right: 20px;font-size: 14px;color: #999999">点赞:{{item[4]}}</span>            <span style="margin-right: 20px;font-size: 14px;color: #999999">评论:{{item[5]}}</span>          </div>          <!-- 右下角信息 -->          <div class="content-bottom">            <span>发布<strong>博客</strong>与 {{item[6]}}</span>          </div>        </div>      </el-main>      <!-- 最底部样式 -->      <el-footer>趁年轻,给自己一个机会,加油! <a href="https://beian.miit.gov.cn/">陕ICP备2021001587号-1</a></el-footer>    </el-container>  </div></template>
复制代码

3.CSS 代码:

单纯的结构层肯定不能凸显一些美,这时候我们需要用 css 来对页面进行具体的美化:



<style scoped>/* 整体框架 */  .homepage {    width: 100%;    height: 100%;  }/* strong标签,标题 */  .content-title strong {    font-size: 28px;  }
/* 顶部文字样式 */ .head-center { width: 1200px; height: 100%; margin: 0 auto; text-align: center; }
/* 切换账号以及退出登陆样式 */ .span_text { float: right; cursor: pointer; font-weight: 600; font-size: 15px; }
/* 鼠标划过样式 */ .span_text:hover { color: #315efb; }
/* 头像 */ .img { margin-right: 10px; width: 50px; height: 50px; line-height: 85px; }
/* 中心内容文本框 */ .content-text { width: 1000px; height: 200px; margin: 0 auto; position: relative; margin-top: 10px; overflow: hidden; background-color: #dfdfdf; cursor: pointer; }
/* 标题 */ .content-title { position: absolute; top: 10px; left: 10px; width: 30%; height: 50px; line-height: 50px; text-align: left; }
/* 中心内容 */ .content-center { position: absolute; top: 60px; left: 10px; width: 98.2%; height: 80px; text-align: left; }
/* 点赞,评论 */ .content-dzpl { position: absolute; bottom: 10px; left: 10px; width: 30%; height: 30px; line-height: 30px }
/* 右下角的信息 */ .content-bottom { position: absolute; bottom: 10px; right: 20px; width: 30%; height: 30px; line-height: 30px; }
.el-dropdown-link { cursor: pointer; color: #409EFF; }
.el-icon-arrow-down { font-size: 12px; }
.demonstration { display: block; color: #8492a6; font-size: 14px; margin-bottom: 20px; }
/* 布局样式 */ .el-header, .el-footer { background-color: #B3C0D1; color: #333; text-align: center; line-height: 60px; }
.el-main { background-color: #E9EEF3; color: #333; text-align: center; line-height: 50px; }
body>.el-container { margin-bottom: 40px; }
.el-container:nth-child(5) .el-aside, .el-container:nth-child(6) .el-aside { line-height: 260px; }
.el-container:nth-child(7) .el-aside { line-height: 320px; }
</style>
复制代码

4.js 代码:

export default {  name: 'homepage',  data () {    return {      text: '',      time: '',      data: '' // 存储拿到的数据    }  },  created () {    var that = this    // 获取信息    that.text = sessionStorage.getItem('user')    // 获取当前时间    that.time = sessionStorage.getItem('time')    // 参数,方便识别当前的用户进行不同用户显示自己的数据    var data = {      username: sessionStorage.getItem('user')    }    // 发送请求    this.$get('/homepage', data).then(res => {      for (var i = 0; i < res.length; i++) {        that.data = res      }    })  },  components: {},  mounted () {},  methods: {    // 时间转换以及补零操作    timestampToTime (timestamp) {      var date = new Date(timestamp * 1000)      var Y = date.getFullYear() + '-'      var M = (date.getMonth() + 1).toString().padStart(2, '0') + '-'      var D = date.getDate().toString().padStart(2, '0') + ' '      var h = date.getHours().toString().padStart(2, '0') + ':'      var m = date.getMinutes().toString().padStart(2, '0') + ':'      var s = date.getSeconds().toString().padStart(2, '0')      return Y + M + D + h + m + s    },    // 点击退出按钮或者切换账号按钮    exit () {      sessionStorage.clear()      this.$router.push({        name: 'login'      })      this.$message({        message: '当前账号已退出',        type: 'success'      })    },    // 点击书写文章    bumittext () {      this.$router.push({        name: 'marktext'      })    }  }}
</script>
复制代码



5.不同用户不同数据:

因为我们在登录时候采用了:


sessionStorage.setItem('sid', '已登录') // 设置本地存储信息sessionStorage.setItem('user', this.user) // 设置本地存储信息,登录用户sessionStorage.setItem('time', this.time) // 设置本地存储信息,登录时间
复制代码


所以我们的首页就会显示,我们当前登录的用户以及登录的时间:


例如:


  1. xxadmin用户登录:

  2. admin用户登录:



四.编写文章(marktext):

首页homepage显示的那样,我们鼠标滑到头像时候会有我们可以执行的操作:



我们主要进行文章编写的讲解,在首页的 js 代码中我们发现有如下的代码:


// 点击书写文章    bumittext () {      this.$router.push({        name: 'marktext'      })    }
复制代码


那么我们来看一下marktext页面,我们使用的是 div 进行书写文本内容,并且进行自适应的操作:


1.HTML 代码:

<template>  <div class="marktext">    <el-container>      <!-- 头部 -->      <el-header>        <div class="head">          <div v-on:click='back'>            <span style="float: left;font-size: 18px"><i class="el-icon-back"></i>文章管理</span>          </div>          <el-input placeholder="请输入标题(5-15字)" v-model="title" clearable>          </el-input>            <span  @click="dialogVisible1 = true" style="float: right;font-size: 18px"><i class="el-icon-position"></i>发布</span>        </div>      </el-header>       <el-dialog title="提示:" :visible.sync="dialogVisible1" width="20%">          <span>确认发布?</span>          <span slot="footer" class="dialog-footer">            <el-button type="primary" @click="send">确认</el-button>            <el-button @click="dialogVisible1 = false">取 消</el-button>          </span>        </el-dialog>      <el-dialog title="温馨提示" :visible.sync="dialogVisible" width="20%">          <span>离开后网站不会保留您的所有内容</span>          <span slot="footer" class="dialog-footer">            <el-button type="primary" @click="exit">离开</el-button>            <el-button @click="dialogVisible = false">取 消</el-button>          </span>        </el-dialog>      <el-main>        <el-row type="flex" class="row-bg release" justify="center">          <el-col :span="12">            <el-card class="box-card">               <div class="textarea" contenteditable="true"><br /></div>            </el-card>          </el-col>        </el-row>      </el-main>    </el-container>  </div></template>
复制代码

2.CSS 代码:

同样我们来进行美化设计:


<style>  /* 整体布局 */  .marktext {    width: 100%;    height: 100%;  }
/* 头部样式 */ .head { width: 80%; height: 100%; margin: 0 auto; }
.head span:hover { cursor: pointer; }
/* 输入框样式 */ .el-input { width: 70%; }
.el-input__inner { border-radius: 30px; display: inline-block; }
.el-header { background-color: #B3C0D1; color: #333; text-align: center; line-height: 60px; }
.el-main { background-color: #E9EEF3; color: #333; text-align: center; line-height: 160px; }
body>.el-container { margin-bottom: 40px; }
.el-container:nth-child(5) .el-aside, .el-container:nth-child(6) .el-aside { line-height: 260px; }
.el-container:nth-child(7) .el-aside { line-height: 320px; } .textarea{ width: 100%; min-height: 20px; max-height: 300px; _height: 120px; margin-left: auto; margin-right: auto; padding: 3px; outline: 0; border: 1px solid #a0b3d6; font-size: 12px; line-height: 24px; padding: 2px; word-wrap: break-word; overflow-x: hidden; overflow-y: auto; border-color: rgba(82, 168, 236, 0.8); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1), 0 0 8px rgba(82, 168, 236, 0.6); text-align: left;}</style>
复制代码

3.js 操作:

(1).返回按钮(文章管理):

我们可以点击文章管理退回我们的homepage首页,当然也会进行退出提示:


 // 返回homepage页面    exit () {      this.$router.push({        name: 'homepage'      })      this.title = ''      this.text = ''    }  },
复制代码


提示的 HTML 代码:


 <el-dialog title="温馨提示" :visible.sync="dialogVisible" width="20%">          <span>离开后网站不会保留您的所有内容</span>          <span slot="footer" class="dialog-footer">            <el-button type="primary" @click="exit">离开</el-button>            <el-button @click="dialogVisible = false">取 消</el-button>          </span>        </el-dialog>
复制代码


效果:


(2).文章发布:

文章发布也就是我们需要进行数据的提交,那么接口请查看(五.Django接口),具体的操作如下:


// 发送数据    send () {      // 文本框的内容      this.text = document.getElementsByClassName('textarea')[0].innerText      // 当前时间      var time = this.timestampToTime(Date.now() / 1000)      // 参数      var data = {        username: sessionStorage.getItem('user'),        title: this.title,        text: this.text,        ctime: time      }      // 提交数据      this.$post('/insert/', data, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}}).then(res => {        this.$message({          message: '发布成功',          type: 'success'        })        this.$router.push({          name: 'homepage'        })      })    },
复制代码


数据提交成功之后返回我们的homepage首页;

(3).整体 js 代码:

<script>export default {  name: 'editor',  data () {    return {      editor: '',      title: '', // 标题      dialogVisible: false,      dialogVisible1: false,      text: ''    }  },  methods: {    // 时间转换以及补零操作    timestampToTime (timestamp) {      var date = new Date(timestamp * 1000)      var Y = date.getFullYear() + '-'      var M = (date.getMonth() + 1).toString().padStart(2, '0') + '-'      var D = date.getDate().toString().padStart(2, '0') + ' '      var h = date.getHours().toString().padStart(2, '0') + ':'      var m = date.getMinutes().toString().padStart(2, '0') + ':'      var s = date.getSeconds().toString().padStart(2, '0')      return Y + M + D + h + m + s    },    back () {      var that = this      that.dialogVisible = true    },    // 发送数据    send () {      // 文本框的内容      this.text = document.getElementsByClassName('textarea')[0].innerText      // 当前时间      var time = this.timestampToTime(Date.now() / 1000)      // 参数      var data = {        username: sessionStorage.getItem('user'),        title: this.title,        text: this.text,        ctime: time      }      // 提交数据      this.$post('/insert/', data, {headers: {'Content-Type': 'application/x-www-form-urlencoded'}}).then(res => {        this.$message({          message: '发布成功',          type: 'success'        })        this.$router.push({          name: 'homepage'        })      })    },    // 返回homepage页面    exit () {      this.$router.push({        name: 'homepage'      })      this.title = ''      this.text = ''    }  },  mounted () {
}}
</script>
复制代码



五.Django 接口:

接 (三.homepage)中我们发送请求的接口需要,在我们上一篇博文从零到一搭建一个属于自己的博客系统(弌)views.py文件中书写以下代码,数据库详情下滑查看(六.数据库):


def homepage(request):    # 获取传来的值    data=request.GET    # 打开数据库连接    # 地址,用户名,密码,数据库名,编码格式    db = MySQLdb.connect("localhost", "root", "", "bolg", charset='utf8')    # 使用cursor()方法获取操作游标    cursor = db.cursor()
# SQL 查询语句 sql = "SELECT * FROM text_table WHERE username='%s'"%data['username'] try: # 执行SQL语句 cursor.execute(sql) # 获取所有记录列表 results = cursor.fetchall()
except: print("Error: unable to fecth data")
db.close() return JsonResponse(results, safe=False) import jsondef insert(request): # 获取传来的值,将数据转化为json格式 data = json.loads(request.body, encoding='utf-8') # 打开数据库连接 # 地址,用户名,密码,数据库名,编码格式 db = MySQLdb.connect("localhost", "root", "", "bolg", charset='utf8') # 使用cursor()方法获取操作游标 cursor = db.cursor()
# SQL 语句 sql = "INSERT INTO text_table(username,title,dz,pl,ctime,text) VALUES ('%s','%s','%s','%s','%s','%s')"%(data['username'],data['title'],0,0,data['ctime'],data['text']) try: # 执行SQL语句 cursor.execute(sql) # 提交到数据库执行 db.commit()
except: # 如果发生错误则回滚 db.rollback() print("Error: unable to fecth data")
db.close() return JsonResponse(data)
复制代码


然后我们在urls.py文件中加入下面的代码:


urlpatterns = [    # 用户登录验证接口    path('login/',views.login),    # 数据展示接口    path('homepage/', views.homepage),    #插入数据接口    path('insert/', views.insert),]
复制代码


因为我们在查找时候加入了条件WHERE username='%s'"%data['username'],也就是前端传来的数据,当前的用户是谁,就显示谁的数据。



六.数据库:

在 (三.homepage首页) 中我们建立的数据库如下所示,表名为text_table:



解释:


  1. id:自增型,唯一的标识;

  2. username:用户名,哪一个用户所提交的数据;

  3. title:文章的标题;

  4. text:发布的文章内容;

  5. dz:点赞数;

  6. pl:评论数;

  7. ctime:发布文章的时间;



七.项目演示:

说了那么多了,我们来看看具体的效果:



成功后数据库的截图:



路由守护部分:




八.总结:

当前项目可执行的操作:

  1. 登录的操作;

  2. 首页信息的显示,不同用户不同数据信息;

  3. 文章的书写,数据库中的文章插入;

  4. session 中的信息判断用户的登录与否,登录的用户...




-- -好了,今天就到这儿了,我要捡瓶子去维持生活了,有人要一起吗?- - -



发布于: 刚刚阅读数: 3
用户头像

木偶

关注

凭时间赢来的东西,时间肯定会为之作证 2022-10-21 加入

CSDN前端领域优质创作者,CSDN博客专家,擅长PC端以及Uniapp开发

评论

发布
暂无评论
从零到一搭建一个属于自己的博客系统(弍)_前端_木偶_InfoQ写作社区