SpringBoot集成Vue3实现的系统(三)

发布时间:2023年12月25日

学习目标:SpringBoot集成Vue3实现的系统(三)小内容完结篇

提示:SpringBoot2与Vue3的小练习图文摘录(三)

例如:

  • 三篇文章带你更熟悉掌握前后端分离的基本实现

新闻模块化操作

在后台的很多实际应用中都存在这很多的内容编辑的处理,所以我们需要使用到的是【富文本编辑器】

在这里插入图片描述

在此我们选择的是vue集成wangEditor

在这里插入图片描述

集成wangeditor编辑器的实现

参考官网即可: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
②、学习文档熟悉组件Toolbar和Editor以及对应的函数

在这里插入图片描述

③、参考在线的demo示例来根据自己的需求进行修改处理

在这里插入图片描述

https://stackblitz.com/edit/vue3-wangeditor-demo?file=src%2Fcomponents%2FBasicEditor.vue

在这里插入图片描述

新增新闻公告模块来使用wangEditor富文本编辑器的使用

①、数据库表
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;
②、后端通过MybatisX插件生成对应的三层代码

在这里插入图片描述

注意实体对象的中如果有时间可以通过JSONFormat注解实现【前端的时间解析就可以去除】
在这里插入图片描述

③、前端中复制一个书籍/用户的vue文件并进行修改

在这里插入图片描述

④、修改查询的请求路径即可

在这里插入图片描述

新增公告的实现

News.vue中的新增公告的对话框

在这里插入图片描述

<!-- 添加公告的对话框 -->
    <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>
script中的实现

参照文档使用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前端与后端分离的小练习就到此结束了,大家可以自行练习,加强学习哦!~~~ 有问题可留言或者评论私我~

小章节完毕,敬请期待后续更新(可留言需要学习哪方面的内容哈)!如果需要源码的朋友们可关注微信公众号"锅锅编程生活"或者扫描二维码关注回复关键字/后台留言获取即可!
在这里插入图片描述

文章来源:https://blog.csdn.net/xu772710255/article/details/135131635
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。