SpringBoot + Vue(前后端分离之博客上传)
Posted HUTEROX
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot + Vue(前后端分离之博客上传)相关的知识,希望对你有一定的参考价值。
通过前面的磨合,总算是习惯了,调整好了,前后端的一些事情。主要是先前前端有一些坑没处理好,导致我这边状况百出,不过还好,只是现在比较容易出问题的那些地方已经解决了,像什么文件上传之类的。那么今天也是实现了博客的上传。
博客表的设计
这里的话不像原来Django的ORM,这里的话还是要自己去键表的。哦对了这里我也将尝试使用mybatisplus完全使用面对对象的写法来实现多表查询(这里的话我还要测试一下,主要是想看看这样写有什么大毛病没有,能不能直接实现)。不然的话mybatisplus的优势真不太大。
博客表
(PS:我这里的数据库命名并不规范,但是先前没反应过来只能将错就错了,原来Django里面直接写得model习惯了,所以当时没反应过来)。
create table userblogs
(
Id bigint auto_increment comment '博文的ID',
Title varchar(24) not null,
UserId bigint not null comment '存储用户的ID,一对多嘛',
BodyId bigint not null comment '存放博文内容 Id 的字段,到时候根据这个去找博客的具体内容',
ShuoMing varchar(256) not null comment '博文的描述,本来我是想要实现前端自己截取一段摘要的
但是有点难',
UpDateTime datetime null,
Autoer varchar(24) not null,
CreateTime datetime null,
IsDelete int default 0 not null comment '逻辑删除,0 表示没有 1 表示被删除',
BlogPic varchar(256) null comment '博客的封面',
Pass int default 0 null comment '文章是否被审核通过 0 没有 1 通过',
constraint UserBlogs_Id_uindex
unique (Id)
)
comment '用户上传的博文,我们这里存储的是博文内容的表的id,
由于根据阿里的规则数据库不允许外键,所以所有的外键由代码
层实现!
';
频道表
目前我暂时砍掉了用户自己创建频道的功能,原因是用户消息系统没做,所以相关的评论收藏点赞都做不了。但是现在还是开发阶段嘛,这个是会不断更新的。(其实很大原因是我前端不想写了,烦呀)
那么这里是官方频道表
create table basechannel
(
Id bigint auto_increment comment '官方频道的主键',
ChannelName varchar(24) not null,
ChannelDesc varchar(256) not null comment '频道的描述
',
ChannelPic varchar(128) null comment '频道封面,不过官方的频道封面是直接在前端就有的',
constraint BaseChannel_ChannelName_uindex
unique (ChannelName),
constraint BaseChannel_Id_uindex
unique (Id)
)
comment '基本的官方频道';
alter table basechannel
add primary key (Id);
博客内容表
我单独把博客内容给拆分出一张表了
create table blogsbody
(
Id bigint auto_increment comment '博客内容的主键',
Body text not null,
UserBlogId bigint null,
constraint BlogsBody_Id_uindex
unique (Id)
)
comment '博客的内容,这里存放的是博客的html代码,
前端完成了博客的页面转化';
alter table blogsbody
add primary key (Id);
拆出来是可以保存用户博客原有的记录,方便文章复原。
中间表
这个主要是频道和博客之间的关系表,其实在当前这个应该是一对多的关系,但是这里还是设计成多对多的关系吧。
create table blogandbasechannel
(
Id bigint auto_increment comment '中间表的主键',
ChannelId bigint not null,
UserBlogsId bigint not null,
constraint BlogAndBaseChannel_Id_uindex
unique (Id)
)
comment '博客和官方频道的中间表
';
alter table blogandbasechannel
add primary key (Id);
关系图
前端页面
这个写博客的前端页面我又改了一下。
<template>
<div class="m_container">
<!-- 博客内容 -->
<div class="m_content">
<el-form ref="editForm" status-icon :model="editForm" label-width="80px">
<input type="text" name="blogname" placeholder="请输入文章标题" v-model="editForm.title">
<el-button id="submit" type="primary" @click="tosubmitForm('editForm')">发布文章</el-button>
<br>
<br>
<mavon-editor
v-model="editForm.content"
ref="md"
@imgAdd="imgAdd"
@change="change"
style="min-height: 800px;width: 100%"
/>
</el-form>
</div>
<!-- 对话框内容 -->
<el-dialog title="发布文章" :visible.sync="dialogFormVisible" width="35%">
<el-form :model="editForm" ref="editForm2">
<el-form-item label="描述" prop="description">
<textarea :maxlength="120"
v-model="editForm.description" style=" width: 80%;height: 150px;border-color: lightgrey;border-radius: 5px"
class="texti" placeholder="请编写博文描述(必填)"
></textarea>
</el-form-item>
<el-form-item label="分类专栏" prop="channel_id" :rules=" required: true, message: '分类专栏不能为空', trigger: 'blur'">
<el-select v-model="editForm.channel_id" placeholder="请选择频道">
<el-option v-for="(item,index) in baseChannels" :key="item.index" :label="item.channelName" :value="item.id + ''"></el-option>
</el-select>
</el-form-item>
<el-form-item label="博客封面" prop="first_picture" >
<el-input v-model="editForm.first_picture" placeholder="请输入封面URL"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" @click="submitBlog('editForm2')">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
import axios from "axios";
export default
name: "Writeboke",
data()
return
editForm: //博客文章表单
title: '',
description: '',
first_picture: '',
content: '',
channel_id: '',
flag:'',
published: null,
,
baseChannels: [], // 进入页面的时候需要被加载的玩意儿
success: null, //交互状态!
editForm2: //用来校验的表单
channel_id: null,
flag:'',
published: null,
,
oldtags:'', //字符串类型的标签
type: //分类专栏
name:''
,
dialogFormVisible: false, //控制发布博客对话框
dialog2: false, //控制新增分类专栏对话框
,
mounted()
//获取频道,本来是打算直接在前端获取的,但是想了想还是算了吧,从服务器这边拿数据吧
this.axios(
url: "/boot/getbasechannels",
method: 'post',
).then(res=>
this.baseChannels = res.data.baseChannels
this.success = res.data.success
if(this.success == '0')
alert("数据加载异常")
)
,
methods:
//去发布文章
toSubmit()
this.dialogFormVisible = true
this.initType()
,
//初始化文章专栏
initType()
,
submitForm(formName)
this.$refs[formName].validate((valid) =>
if (valid)
this.addNewType()
else
return false;
);
,
//校验博客基本内容表单
tosubmitForm(formName)
if(this.editForm.title == '')
alert("文章标题不能为空")
return
if(this.editForm.content == '')
alert("文章内容不能为空")
return
this.toSubmit()
,
//校验发布博客表单,校验成功后发布博客
submitBlog(formName)
if(this.editForm.description == '')
alert("文章描述不能为空")
this.$refs[formName].validate((valid) =>
if (valid)
//发布博客
this.axios(
url: "/boot/saveblog",
method: "post",
data:
boke: this.editForm
,
headers:
"token": localStorage.getExpire("tokenhole"),
).then(res=>
if(res.data.success == 0)
alert("博客发送失败")
return
alert("博客发布成功")
this.dialogFormVisible = false
)
console.log("博客发布")
else
return false;
);
,
imgAdd(pos, $file)
let param = new FormData()
param.append("file",$file)
this.axios(
url: "/boot/boke/bokeImg",
method: "post",
data: param,
headers:
'Content-Type': 'multipart/form-data',
"token": localStorage.getExpire("tokenhole"),
).then(res=>
if(res.data.success == 0)
alert("图片上传失败")
return
let url = "/boot"+ res.data.bokeImg
this.$refs.md.$img2Url(pos,url)
)
,
// 所有操作都会被解析重新渲染
change(value, render) //value为编辑器中的实际内容,即markdown的内容,render为被解析成的html的内容
this.html = render;
,
// 提交
submit() //点击提交后既可以获取html内容,又可以获得markdown的内容,之后存入到服务端就可以了
console.log(this.editForm.content);
console.log(this.html);
,
</script>
<style>
.m_container
margin-top: 20px;
.el-tag + .el-tag
margin-left: 10px;
.button-new-tag
margin-left: 10px;
height: 32px;
line-height: 30px;
padding-top: 0;
padding-bottom: 0;
.input-new-tag
width: 90px;
margin-left: 10px;
vertical-align: bottom;
input
width: 85%;
height: 30px;
border-width: 2px;
border-radius: 5px;
border-color: #00c4ff;
border-bottom-color: #2C7EEA;
color: #586e75;
font-size: 15px;
#submit
width: 10%;
height: 35px;
border-width: 0px;
margin-left: 3%;
border-radius: 10px;
background: #1E90FF;
cursor: pointer;
outline: none;
color: white;
font-size: 17px;
#submit:hover
background-color: #1E90FF;
box-shadow: 0 4px 0 powderblue;
.texti:focus
border-color: #1e88e1;
outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)
textarea
resize: none;
</style>
主要是搞了个弹出,然后显示一下提交的玩意。
这里前端又两个接口,要注意,一个是获取 官方频道的,一个就是提交的。
后端频道接口
这个就是获取频道的没啥
@PostMapping("/getbasechannels")
public BaseChannelMessage GetAllChannels()
try
List<BaseChannel> baseChannels = baseChannelServer.GetAllChannel();
baseChannelMessage.setSuccess(1);
baseChannelMessage.setBaseChannels(baseChannels);
return baseChannelMessage;
catch (Exception e)
baseChannelMessage.setSuccess(0);
return baseChannelMessage;
SpringBoot 前后端分离Vue个人博客系统
博客基于SpringBoot+vue的前后端分离颜值博客系统
前后端分离博客项目(SpringBoot/Redis/Shiro/Swagger/MyBatis-Plus/Vue/ElementUI)
Vue+SpringBoot超详细!一周开发一个SpringBoot + Vue+MybatisPlus+Shiro+JWT+Redis前后端分离个人博客项目!!!项目完结