从零到一搭建一个属于自己的博客系统 (弍)
- 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 json
def 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开发
评论