从零到一搭建一个属于自己的博客系统 (弍)
- 2022-10-24 陕西
本文字数:8773 字
阅读完需:约 29 分钟

前言:在上篇博客从零到一搭建一个属于自己的博客系统(弌)中我们讲到了登录界面以及功能的实现,接下来我们来看看首页制作以及文章的发布。
环境:vue+webpack
请求的发送:axios
后端接口:Django
数据库: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"> <em>|</em> </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 来对页面进行具体的美化:
咱们页面使用的是
element-ui中的(Container 布局容器)- -
<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) // 设置本地存储信息,登录时间
所以我们的首页就会显示,我们当前登录的用户以及登录的时间:
例如:
xxadmin用户登录:
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:
解释:
id:自增型,唯一的标识;
username:用户名,哪一个用户所提交的数据;
title:文章的标题;
text:发布的文章内容;
dz:点赞数;
pl:评论数;
ctime:发布文章的时间;
七.项目演示:
说了那么多了,我们来看看具体的效果:
成功后数据库的截图:
路由守护部分:
八.总结:
当前项目可执行的操作:
登录的操作;
首页信息的显示,不同用户不同数据信息;
文章的书写,数据库中的文章插入;
session 中的信息判断用户的登录与否,登录的用户...
-- -好了,今天就到这儿了,我要捡瓶子去维持生活了,有人要一起吗?- - -
版权声明: 本文为 InfoQ 作者【木偶】的原创文章。
原文链接:【http://xie.infoq.cn/article/6e1bb76f2d8de2edf34e025b4】。文章转载请联系作者。
木偶
凭时间赢来的东西,时间肯定会为之作证 2022-10-21 加入
CSDN前端领域优质创作者,CSDN博客专家,擅长PC端以及Uniapp开发










评论