Springboot+Vue实现发表文章功能
点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐]
效果图
前端编辑页面
文章列表页面
文章详情页面
环境介绍
JDK:1.8
数据库:Mysql5.6
前端:Vue
后端:SpringBoot
核心代码介绍
AtricleCtrle.class
public class ArticleCtrler
{
private ArticleService articleService;
public Object addarticle( Article vo)
{
try
{
articleService.insert(vo);
return Result.success(null);
}
catch (Exception e)
{
e.printStackTrace();
}
return Result.error(CodeMsg.SERVER_ERROR);
}
public Object loadPage( Article_Condit vo)
{
try
{
PageInfo
loadPage = articleService.loadPage(vo); return Result.success(loadPage);
}
catch (Exception e)
{
e.printStackTrace();
}
return Result.error(CodeMsg.SERVER_ERROR);
}
}
ArticleService.interface
public interface ArticleService
{
void insert(Article vo);
PageInfo
loadPage(Article_Condit vo) ;}
ArticleServiceImpl.class
public class ArticleServiceImpl implements ArticleService
{
private ArticleDao articleDao;
public void insert(Article vo)
{
vo.setCreatedatetime(new Timestamp(new Date().getTime()));
vo.setCreateuserid("system");
articleDao.save(vo);
}
public PageInfo
loadPage(Article_Condit vo) {
PageHelper.startPage(vo.getPageIndex()==null?0:vo.getPageIndex(), vo.getPageSize()==null?0:vo.getPageSize());
List
findByCondit = articleDao.findByCondit(vo); return new PageInfo
(findByCondit); }
}
ArticleDao.class
public interface ArticleDao
{
void save(Article vo);
List
findByCondit(Article_Condit vo) ;}
Helloworld.vue
"发布文章", description="发布文章") (value=
public class Article implements Serializable
{
private static final long serialVersionUID = 1L;
"文章编号",hidden = true) (value =
private Long id;
"文章标题",required = true) (value =
"标题不能为空") (message =
private String title;
"文章描述",required = true) (value =
"文章描述不能为空") (message =
private String description;
"文章内容",required = true) (value =
"文章内容不能为空") (message =
private String content;
"文章类型",required = false) (value =
private String articletype;
"创建时间",hidden = true) (value =
"yyyy-MM-dd HH:mm", timezone="GMT+8") (pattern=
private Timestamp createdatetime;
"创建人",hidden = true) (value =
private String createuserid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Timestamp getCreatedatetime() {
return createdatetime;
}
public void setCreatedatetime(Timestamp createdatetime) {
this.createdatetime = createdatetime;
}
public String getCreateuserid() {
return createuserid;
}
public void setCreateuserid(String createuserid) {
this.createuserid = createuserid;
}
public String getArticletype() {
return articletype;
}
public void setArticletype(String articletype) {
this.articletype = articletype;
}
public String toString() {
return "Article [id=" + id + ", title=" + title + ", description=" + description + ", content=" + content
+ ", articletype=" + articletype + ", createdatetime=" + createdatetime + ", createuserid="
+ createuserid + "]";
}
}
<mapper namespace="com.yxyz.dao.ArticleDao">
<insert id="save" parameterType="com.yxyz.vo.Article">
insert
into t_article(title,description,content,articletype,createdatetime,createuserid)
values
(
#{title,jdbcType=VARCHAR},#{description,jdbcType=VARCHAR},#{content,jdbcType=LONGVARCHAR},
#{articletype,jdbcType=VARCHAR},#{createdatetime,jdbcType=TIMESTAMP},#{createuserid,jdbcType=VARCHAR}
)
insert>
<select id="findByCondit" parameterType="com.yxyz.condit.Article_Condit" resultType="com.yxyz.vo.Article">
select t1.* from t_article t1 where 1=1
<if test="articletype != null and articletype !=''">
and t1.articletype like concat('%',#{articletype},'%')
if>
<if test="createuserid != null and createuserid !=''">
and t1.createuserid = #{createuserid}
if>
select>
mapper>
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI)
Vue.config.productionTip = false
new Vue({
router,
render: (h) => h(App),
}).$mount('#app')
About.vue
<template>
<div class>
<h3>编辑页面h3>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="标题">
<el-input v-model="form.title">el-input>
el-form-item>
<el-form-item label="描述">
<el-input v-model="form.description">el-input>
el-form-item>
<el-form-item label="正文">
<quill-editor
ref="myQuillEditor"
class="editor"
v-model="form.content"
:options="editorOption"
@blur="onEditorBlur($event)"
@focus="onEditorFocus($event)"
@ready="onEditorReady($event)"
/>
el-form-item>
<el-button class="btn" block type="primary" @click="submit">提交el-button>
el-form>
div>
template>
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import { quillEditor } from 'vue-quill-editor'
import axios from 'axios'
export default {
components: { quillEditor },
props: {},
data() {
return {
form: {
title: '',
description: '',
content: '',
},
editorOption: {
modules: {
toolbar: [
['bold', 'italic', 'underline', 'strike'], //加粗,斜体,下划线,删除线
['blockquote', 'code-block'], //引用,代码块
[{ header: 1 }, { header: 2 }], // 标题,键值对的形式;1、2表示字体大小
[{ list: 'ordered' }, { list: 'bullet' }], //列表
[{ script: 'sub' }, { script: 'super' }], // 上下标
[{ indent: '-1' }, { indent: '+1' }], // 缩进
[{ direction: 'rtl' }], // 文本方向
[{ size: ['small', false, 'large', 'huge'] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], //几级标题
[{ color: [] }, { background: [] }], // 字体颜色,字体背景颜色
[{ font: [] }], //字体
[{ align: [] }], //对齐方式
['clean'], //清除字体样式
// ['image', 'video'], //上传图片、上传视频
],
},
theme: 'snow',
},
}
},
computed: {},
created() {},
mounted() {},
watch: {},
methods: {
onEditorBlur(quill) {
console.log('editor blur!', quill)
},
onEditorFocus(quill) {
console.log('editor focus!', quill)
},
onEditorReady(quill) {
console.log('editor ready!', quill)
},
submit() {
if (!this.form.title) {
this.$message('请输入标题')
}
if (!this.form.description) {
this.$message('请输入描述')
}
if (!this.form.content) {
this.$message('请输入正文')
}
let formData = new FormData()
formData.append('title', this.form.title)
formData.append('description', this.form.description)
formData.append('content', this.form.content)
// 发送 POST 请求
axios({
method: 'post',
url: 'http://139.159.147.237:8080/yxyz/article/addarticle',
data: formData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
})
.then(function(response) {
if (res.code === 0) {
this.$message('提交成功')
}
// this.form = {
// title: '',
// description: '',
// content: '',
// }
this.$router.goBack()
})
.catch(function(error) {
console.log(error)
})
},
},
}
script>
<style scoped lang="less">
.editor {
height: 500px;
}
.btn {
margin-top: 100px;
}
style>
Detail.vue
<template>
<div class="">
<h2>文章详情h2>
<el-card>
<div class="title">{{ detail.title }}div>
<div class="des">{{ detail.description }}div>
<div class="con" v-html="detail.content">div>
<div class="time">{{ detail.createdatetime }}div>
el-card>
div>
template>
<script>
export default {
components: {},
props: {},
data() {
return {
detail: {},
}
},
computed: {},
created() {
console.log(this.$route)
let item = this.$route.params.item
this.detail = item
},
mounted() {},
watch: {},
methods: {},
}
script>
<style scoped lang="less">
.title {
font-weight: bold;
font-size: 16px;
text-align: left;
margin-bottom: 10px;
}
.des {
font-size: 14px;
text-align: left;
margin-bottom: 10px;
}
.con {
font-size: 14px;
text-align: left;
margin-bottom: 10px;
}
.time {
font-size: 14px;
text-align: left;
}
style>
Home.vue
<template>
<div class="">
<h2>文章详情h2>
<el-card>
<div class="title">{{ detail.title }}div>
<div class="des">{{ detail.description }}div>
<div class="con" v-html="detail.content">div>
<div class="time">{{ detail.createdatetime }}div>
el-card>
div>
template>
<script>
export default {
components: {},
props: {},
data() {
return {
detail: {},
}
},
computed: {},
created() {
console.log(this.$route)
let item = this.$route.params.item
this.detail = item
},
mounted() {},
watch: {},
methods: {},
}
script>
<style scoped lang="less">
.title {
font-weight: bold;
font-size: 16px;
text-align: left;
margin-bottom: 10px;
}
.des {
font-size: 14px;
text-align: left;
margin-bottom: 10px;
}
.con {
font-size: 14px;
text-align: left;
margin-bottom: 10px;
}
.time {
font-size: 14px;
text-align: left;
}
style>
application.yml
spring:
profiles:
active: dev
application-dev.yml
server:
port: 8080
servlet:
/yxyz :
spring:
datasource:
name: yxyz
url: jdbc:mysql://localhost/test?serverTimezone=GMT%2b8&characterEncoding=UTF8
username: root
password: 123
# 使用druid数据源
type: com.alibaba.druid.pool.DruidDataSource
com.mysql.cj.jdbc.Driver :
filters: stat
maxActive: 20
initialSize: 1
maxWait: 60000
minIdle: 1
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 'x'
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxOpenPreparedStatements: 20
## 该配置节点为独立的节点
mybatis:
classpath:mapping/*Mapper.xml #注意:一定要对应mapper映射xml文件的所在路径 :
com.yxyz.vo # 注意:对应实体类的路径 :
#打印sql最终填充的参数值
org.apache.ibatis.logging.stdout.StdOutImpl :
觉得本文对你有帮助?请分享给更多人
关注「全栈开发者社区」加星标,提升全栈技能
本公众号会不定期给大家发福利,包括送书、学习资源等,敬请期待吧!
如果感觉推送内容不错,不妨右下角点个在看转发朋友圈或收藏,感谢支持。
好文章,留言、点赞、在看和分享一条龙吧❤️
评论