通过前面的磨合,总算是习惯了,调整好了,前后端的一些事情。主要是先前前端有一些坑没处理好,导致我这边状况百出,不过还好,只是现在比较容易出问题的那些地方已经解决了,像什么文件上传之类的。那么今天也是实现了博客的上传。
博客表的设计
这里的话不像原来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){
this.html = render;
},
submit(){
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;
}
}
然后在前端显示的效果就是
后端博文保存
这个其实也没啥,要注意的就是用了事务。
@EnableTransactionManagement 在你的配置类开启 然后使用
效果
这里的话接口还没写完,主要是前端还有点毛病没办法直观演示。
|