提示:SpringBoot2与Vue3的小练习图文摘录(三)
例如:
在后台的很多实际应用中都存在这很多的内容编辑的处理,所以我们需要使用到的是【富文本编辑器】
参考官网即可:https://www.wangeditor.com/v5/for-frame.html#vue3
yarn add @wangeditor/editor
# 或者 npm install @wangeditor/editor --save
yarn add @wangeditor/editor-for-react
# 或者 npm install @wangeditor/editor-for-react --save
https://stackblitz.com/edit/vue3-wangeditor-demo?file=src%2Fcomponents%2FBasicEditor.vue
CREATE TABLE `t_news` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT COMMENT '公告主键编号',
`title` VARCHAR ( 255 ) DEFAULT NULL COMMENT '标题',
`content` TEXT COMMENT '内容',
`author` VARCHAR ( 255 ) DEFAULT NULL COMMENT '作者',
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
`update_time` DATETIME DEFAULT NULL COMMENT '修改时间',
`create_user` INT ( 11 ) DEFAULT NULL COMMENT '创建用户编号',
`update_user` INT ( 11 ) DEFAULT NULL COMMENT '修改公告用户编号',
`deleted` INT ( 11 ) DEFAULT '0' COMMENT '逻辑删除【默认值为0】',
PRIMARY KEY ( `id` )
) ENGINE = INNODB AUTO_INCREMENT = 8 DEFAULT CHARSET = utf8;
注意实体对象的中如果有时间可以通过JSONFormat注解实现【前端的时间解析就可以去除】
<!-- 添加公告的对话框 -->
<el-dialog v-model="dialogVisible" title="公告信息" width="80%">
<el-form :model="form" label-width="120px" >
<el-form-item label="公告标题:">
<el-input v-model="form.title" style="width: 80%;" />
</el-form-item>
<!-- <el-form-item label="作 者:">
<el-input v-model="form.author" style="width: 80%;" />
</el-form-item> -->
<!-- 公告的内容 -->
<el-form-item label="内 容:">
<div style="border: 1px solid #ccc">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="height: 400px; overflow-y: hidden;"
v-model="form.content"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="handleCreated"
@onChange="handleChange"
@onDestroyed="handleDestroyed"
@onFocus="handleFocus"
@onBlur="handleBlur"
@customAlert="customAlert"
@customPaste="customPaste"
/>
</div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="save">确认</el-button>
</span>
</template>
</el-dialog>
参照文档使用vue3的特性来写
<script>
import { getData, postData } from "../utils/remote";
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import {h} from "vue"
import { onBeforeUnmount, ref, shallowRef, onMounted,reactive,toRefs } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { ElNotification } from "element-plus";
export default {
name:"News",
components: { Editor, Toolbar },
setup() {
const state=reactive({
form: {},
total: 0,
dialogVisible: false,
search: "",
currentPage: 1,
pageSize: 5,
tableData: []
});
// 编辑器实例,必须用 shallowRef,重要!
const editorRef = shallowRef();
// 内容 HTML
const valueHtml = ref('<p>hello</p>');
// 模拟 ajax 异步获取内容
onMounted(() => {
setTimeout(() => {
valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>';
}, 1500);
});
const toolbarConfig = {};
const editorConfig = { placeholder: '请输入内容...' };
// 组件销毁时,也及时销毁编辑器,重要!
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
// 编辑器回调函数
const handleCreated = (editor) => {
console.log('created', editor);
editorRef.value = editor; // 记录 editor 实例,重要!
};
const handleChange = (editor) => {
console.log('change:', editor.getHtml());
};
const handleDestroyed = (editor) => {
console.log('destroyed', editor);
};
const handleFocus = (editor) => {
console.log('focus', editor);
};
const handleBlur = (editor) => {
console.log('blur', editor);
};
const customAlert = (info, type) => {
alert(`【自定义提示】${type} - ${info}`);
};
const customPaste = (editor, event, callback) => {
console.log('ClipboardEvent 粘贴事件对象', event);
// 自定义插入内容
// editor.insertText('xxx');
// 返回值(注意,vue 事件的返回值,不能用 return)
// callback(false); // 返回 false ,阻止默认粘贴行为
callback(true) // 返回 true ,继续默认的粘贴行为
};
const insertText = () => {
const editor = editorRef.value;
if (editor == null) return;
editor.insertText('hello world');
};
const printHtml = () => {
const editor = editorRef.value;
if (editor == null) return;
console.log(editor.getHtml());
};
const disable = () => {
const editor = editorRef.value;
if (editor == null) return;
editor.disable()
};
load();
//查询所有的公告信息
function load(){
getData("news/loadAllByPage", {
pageNum: state.currentPage,
pageSize: state.pageSize,
search: state.search,
}).then((res) => {
console.log(res);
state.tableData = res.data.records;
state.total = res.data.total;
});
}
//打开新增公告的对话框
function add(){
state.dialogVisible = true;
state.form = {};
handleCreated();
}
//点击保存触发的事件
function save(){
const editor=editorRef.value;
if(editor==null)return;
state.form.content=editor.getHtml();
console.log("获取的内容:"+editor.getHtml());
//新增和修改是共用的
if(state.form.id){
//更新
//获取当前登录的用户名
let users=JSON.parse(sessionStorage.getItem("user")||"{}");
state.form.author=users.nickname;
//发起请求
postData("news/edit",state.form).then(res=>{
console.log(res.data);
if (res.data) {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"成功修改公告信息!"),
type: 'success'
});
} else {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"修改公告信息失败!"),
type: 'error'
});
}
state.dialogVisible = false;
load();//重新加载信息
});
}else{
//新增
//获取当前登录的用户名
let users=JSON.parse(sessionStorage.getItem("user")||"{}");
state.form.author=users.nickname;
//发起请求
postData("news/save",state.form).then(res=>{
console.log(res.data);
if (res.data) {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"成功发布公告信息!"),
type: 'success'
});
} else {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"发布公告信息失败!"),
type: 'error'
});
}
state.dialogVisible = false;
load();//重新加载信息
});
}
}
function handleEdit(row){
if(!editorRef){
const editors=editorRef.value;
editors.insertText(row.content);
}
state.form=JSON.parse(JSON.stringify(row));
state.dialogVisible=true;
}
function handleDelete(id){
postData("news/"+id).then(res=>{
if (res.data) {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"成功删除公告信息!"),
type: 'success'
});
load();//重新加载
} else {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"删除公告信息失败!"),
type: 'error'
});
}
});
}
function handleSizeChange(pageSize) {
//改变当前页的页大小触发
state.pageSize = pageSize;
load();
}
function handleCurrentChange(pageNum) {
//改变当前页的时候触发
state.currentPage = pageNum;
load();
}
return {
...toRefs(state),
editorRef,
valueHtml,
mode:"default", // 或 'simple'
toolbarConfig,
editorConfig,
handleCreated,
handleChange,
handleDestroyed,
handleFocus,
handleBlur,
customAlert,
customPaste,
load,
add,
insertText,
printHtml,
disable,
save,
handleSizeChange,
handleCurrentChange,
handleEdit,
handleDelete
};
}
}
//点击保存触发的事件
function save(){
const editor=editorRef.value;
if(editor==null)return;
state.form.content=editor.getHtml();
console.log("获取的内容:"+editor.getHtml());
//新增和修改是共用的
if(state.form.id){
//更新
//获取当前登录的用户名
let users=JSON.parse(sessionStorage.getItem("user")||"{}");
state.form.author=users.nickname;
//发起请求
postData("news/edit",state.form).then(res=>{
console.log(res.data);
if (res.data) {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"成功修改公告信息!"),
type: 'success'
});
} else {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"修改公告信息失败!"),
type: 'error'
});
}
state.dialogVisible = false;
load();//重新加载信息
});
}else{
//新增
//获取当前登录的用户名
let users=JSON.parse(sessionStorage.getItem("user")||"{}");
state.form.author=users.nickname;
//发起请求
postData("news/save",state.form).then(res=>{
console.log(res.data);
if (res.data) {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"成功发布公告信息!"),
type: 'success'
});
} else {
ElNotification({
title: "温馨提示",
message: h("i",{style:'color:teal'},"发布公告信息失败!"),
type: 'error'
});
}
state.dialogVisible = false;
load();//重新加载信息
});
}
}
function handleEdit(row){
if(!editorRef){
const editors=editorRef.value;
editors.insertText(row.content);
}
state.form=JSON.parse(JSON.stringify(row));
state.dialogVisible=true;
}
package com.xuguoguo.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuguoguo.commons.Result;
import com.xuguoguo.entity.Book;
import com.xuguoguo.entity.News;
import com.xuguoguo.service.NewsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
@Package: com.xuguoguo.controller
@ClassName: BookController
@Author: XuGuoGuo
@CreateTime: 2023/12/12-16:40
@Description:
*/
@RestController
@RequestMapping("/news")
public class NewsController {
//注入service
@Autowired
private NewsService newsService;
@RequestMapping("/loadAll")
public Result loadAll(){
List<News> list = newsService.list();
return Result.of(list);
}
@RequestMapping("/loadAllByPage")
public Result loadAllByPage(@RequestParam("pageNum")Integer pageNum,
@RequestParam("pageSize")Integer pageSize,
String search){
//通过分页的插件【拦截器】
Page<News> pages = new Page<>(pageNum, pageSize);
//构造条件构造器
QueryWrapper<News> bookQueryWrapper = new QueryWrapper<>();
if (search!=null&& !"".equals(search)) {
bookQueryWrapper.like("title",search);
}
Page<News> page = newsService.page(pages, bookQueryWrapper);
return Result.of(page);
}
@RequestMapping("/save")
public Result save(@RequestBody News news){
//调用service实现新增用户
boolean save = newsService.save(news);
return Result.of(save);
}
@RequestMapping("/edit")
public Result edit(@RequestBody News news){
boolean b = newsService.updateById(news);
return Result.of(b);
}
@RequestMapping("/{id}")
public Result deleted(@PathVariable("id")Integer id){
boolean b = newsService.removeById(id);
return Result.of(b);
}
@RequestMapping("/delBatch")
public Result delBatch(@RequestBody List<Integer> ids){
//调用service中的批量删除实现
boolean b = newsService.removeBatchByIds(ids);
return Result.of(b);
}
}
vue前端与后端分离的小练习就到此结束了,大家可以自行练习,加强学习哦!~~~ 有问题可留言或者评论私我~
小章节完毕,敬请期待后续更新(可留言需要学习哪方面的内容哈)!如果需要源码的朋友们可关注微信公众号"锅锅编程生活"或者扫描二维码关注回复关键字/后台留言获取即可!