找回密码
 立即注册
首页 业界区 业界 Springboot3 + Vue3 整合tinymce富文本编辑器

Springboot3 + Vue3 整合tinymce富文本编辑器

粒浊 2025-6-6 16:12:29
后端Springboot图片/视频上传接口:

注意!我这里的写法是通过RedisTemplate将图片和视频文件上传到Github仓库,再用jsdelivr去访问的,这里贴的代码不完整。

如果是上传到其它如阿里云、七牛云、又拍云等云存储平台,或者直接存到云服务器上的话,网上都有很多教程可以搜,直接拿来用就对了。

 
  1.  /**
  2.   * Github图片上传
  3.   *
  4.   * @param multipartFile
  5.   * @return
  6.   * @throws IOException
  7.   */
  8.  @PostMapping("/github/upload")
  9.  public Object upload(@RequestParam(value = "file") MultipartFile multipartFile) throws IOException {
  10.      return Result.success(this.githubUploader.upload(multipartFile));
  11.  }
  12.  ​
  13.  /**
  14.   * Github视频上传
  15.   *
  16.   * @param multipartFile
  17.   * @return
  18.   * @throws IOException
  19.   */
  20.  @PostMapping("/github/video/upload")
  21.  public Object uploadVideo(@RequestParam(value = "file") MultipartFile multipartFile) throws IOException {
  22.      return Result.success(this.githubUploader.upload(multipartFile));
  23.  }
复制代码
 
yml文件还要配置一下mutipart中max-file-size和max-request-size的值,一般后者要比前者大,因为是前端请求自带的一些数据再加上传的文件大小,这里我分别设置的是5MB和10MB。

 
 
前端Vue3:

先贴一下tinymce的原版和中文版开发文档:

TinyMCE 7 官方文档
TinyMCE中文文档中文手册 (ax-z.cn)
 
安装依赖

vue3下载命令:
  1.  npm install @tinymce/tinymce-vue -S
复制代码
  1.  npm install tinymce -S
复制代码
上面两条命令都要执行

 
汉化(安装语言包)

编辑器本身是英文的,所以还要下载本地化文件 TinyMCE语言包

下载这个:

1.png

 
在public下创建“tinymce”目录

2.png

在node_modules找到"tinymce"依赖下的"skins",将其拷贝到public目录下的"tinymce"中, 同理将刚刚下载完成的"zh-CN"放到"public/langs"

 
创建自定义组件封装tinymce编辑器

 
在components下创建一个自定义组件,命名为“TEditor”(这里取什么名都可,这里是我的命名)

如果只需要去发布内容,打开编辑器的时候没有文字,直接上手编辑的话,把下面的直接CV到TEditor.vue中即可

 
  1.  <template>
  2.    
  3.      <editor
  4.          v-model="myValue"
  5.          :init="init"
  6.          :enabled="enabled"
  7.          :id="tinymceId"
  8.      ></editor>
  9.    
  10.  </template>
  11.  
  12.  
  13.  
  14.  
复制代码
 
引用自定义组件:
  1.  <template>
  2.    
  3.      <TEditor ></TEditor>
  4.    
  5.  </template>
  6.  
  7.  
复制代码
 
3.png

 
 
但是现在的我还没系统地去学vue,不知道如何去做父子间通讯。就是,假设我在父组件中绑定的v-model="htmlTxt",当赋值给htmlTxt.value时,富文本上无法接收回显我赋值的内容,即在需要编辑已发布的文章内容时,打开编辑器后文章内容没有回显。所以我在这里讲一下我个人比较笨的做法。

 
个人做法(不封装,直接塞)

就是把刚才那一大面的自定义组件里的编辑器配置代码直接塞到父组件里,然后就不存在父子通讯的问题了,

父组件template中
  1.  <editor
  2.       :validate-event="false"
  3.      v-model="myValue"
  4.      :init="init"
  5.      :enabled="enabled"
  6.      :id="tinymceId">
  7.  </editor>
复制代码
 
然后这是js部分的相关代码
  1.  // 新闻编辑
  2.  const editNews = (row) => {
  3.    editVisible.value = true // 点击编辑按钮时打开el-dialog对话框
  4.    formModel.value.modId = row.id // 依次获取表单中的数据
  5.    formModel.value.modNewsTitle = row.newsTitle
  6.    formModel.value.modNewsContent = row.newsContent
  7.    setTimeout(() => myValue.value = row.newsContent, 0) //模拟Ajax的方式去延时给编辑器上绑定的myValue参数赋值
  8.  }
  9.  ​
  10.  ​
  11.  // 确认修改新闻
  12.  const submitForm = async () => {
  13.    await tinymce.init({}) // 因为编辑器是被包在el-dialog里的,所以打开对话框再初始化加载
  14.    formModel.value.modNewsContent = myValue.value // 把编辑器上绑定获取到的数据赋值给表单对象
  15.    await form.value.validate() // 表单参数校验
  16.    const res = await newsModService({  // 请求修改新闻的后端接口
  17.      id: formModel.value.modId,
  18.      newsTitle: formModel.value.modNewsTitle,
  19.      newsContent: formModel.value.modNewsContent
  20.    })
  21.    if (res.data.code === 0) {  // 后端返回状态码为0,即修改成功
  22.      tableLoading.value = true // 这是定义的一个表格加载时,是否显示加载动画的boolean参数
  23.      await listRenderPage() //这是向后端请求新闻列表的方法,修改完之后再请求一下,重载刷新页面的数据
  24.      tableLoading.value = false
  25.      form.value.resetFields()  // 清空表单校验的数据
  26.      formModel.value.modNewsContent = '' // 这里是定义了一个formModel对象,包了三个参数
  27.      formModel.value.modId = ''
  28.      formModel.value.modNewsTitle = ''
  29.      myValue.value = ''  // 修改完之后全部数据初始化
  30.      editVisible.value = false  // 这是控制el-dialog对话框是否显示的一个boolean参数,这里改完就关闭
  31.      ElMessage.success('修改成功')
  32.    } else {
  33.      editVisible.value = false
  34.      ElMessage.error(res.data.message || '修改失败,请稍后重试')
  35.    }
  36.  }
复制代码
 
这样就可以实现编辑时,数据能回显到编辑器上面了,效果如下:

 
https://jsd.onmicrosoft.cn/gh/Albert-PZY/blue-earth/typora/recording.gif
 
 
前端Vue3图片/文件上传:

因为开发文档我实在看不懂,不知道怎么调tinymce自带的图片和视频上传方法

所以我还是用了笨方法,说一下我的思路,很简单,就是用两个el-upload,分别控制上传图片、上传视频的参数校验和请求后端上传接口的操作,当请求到后端返回的url后,再手写
<img />
和标签,把url绑定到src上,把这个标签以String类型的格式追加到tinymce绑定的myValue参数上,就可以实现图片和视频上传并回显到tinymce上的操作了。


 
下面附上整个操作的基本代码

 
template中
  1.  <editor
  2.       :validate-event="false"
  3.      v-model="myValue"
  4.      :init="init"
  5.      :enabled="enabled"
  6.      :id="tinymceId">
  7.  </editor>       图片上传                     图片大小限制在1MB以内                       视频上传                     视频大小限制在2MB以内                
复制代码
 
js中
  1. // 上传图片前的格式校验
  2. const beforeUploadImg = (file) => {
  3.     // 校验图片格式
  4.   const fileSuffix = file.name.substring(file.name.lastIndexOf(".") + 1); // 获取文件后缀名
  5.   const whiteList = ["png", "jpg", "gif"]; // 自定义筛选的图片格式类型
  6.   if (whiteList.indexOf(fileSuffix) === -1) {
  7.     alert('上传图片仅支持 png、jpg、gif 格式');
  8.     return false;
  9.   }
  10.     // 校验图片文件大小
  11.   const isLt1M = file.size / 1024 / 1024 < 1;
  12.   if (!isLt1M) {
  13.     alert('上传文件大小不能超过 1MB');
  14.     return false;
  15.   }
  16. }
  17. // 图片上传成功后,记录后端返回的图片URL地址
  18. const handleImgUploadSuccess = async (response, file, fileList) => {
  19.   // 确保response.data是字符串类型
  20.   const imageUrl = await response.data.toString();
  21.   if (response.code === 0) {
  22.     ElMessage.success("图片上传成功")
  23.     // 使用Vue的v-bind指令来绑定图片的src属性
  24.     imgUpload.value = `<img src="https://www.cnblogs.com/${imageUrl}" alt=""  />`;
  25.     setTimeout(() => myValue.value += imgUpload.value)
  26.   } else {
  27.     ElMessage.error(response.message || "上传失败,请稍后重试")
  28.   }
  29. }
  30. // 上传视频前的格式校验
  31. const beforeUploadVideo = (file) => {
  32.   const fileSuffix = file.name.substring(file.name.lastIndexOf(".") + 1);
  33.   const whiteList = ["mp4"];
  34.   if (whiteList.indexOf(fileSuffix) === -1) {
  35.     alert('上传视频仅支持 mp4 格式');
  36.     return false;
  37.   }
  38.   const isLt2M = file.size / 1024 / 1024 < 2;
  39.   if (!isLt2M) {
  40.     alert('上传文件大小不能超过 2MB');
  41.     return false;
  42.   }
  43.   return confirm('视频上传将会比较耗时,需要等待30秒左右,您确定要上传吗?');
  44. }
  45. // 视频上传成功后,记录后端返回的视频URL地址
  46. const handleVideoUploadSuccess = async (response, file, fileList) => {
  47.   // 确保response.data是字符串类型
  48.   const videoUrl = await response.data.toString();
  49.   if (response.code === 0) {
  50.     ElMessage.success("图片上传成功")
  51.     // 使用Vue的v-bind指令来绑定图片的src属性
  52.     videoUpload.value = `<video  poster="" controls="controls" width="498" height="249"> <source src="${videoUrl}" type="video/mp4"></video>`;
  53.     setTimeout(() => myValue.value += videoUpload.value)
  54.   } else {
  55.     ElMessage.error(response.message || "上传失败,请稍后重试")
  56.   }
  57. }
复制代码
 
 
效果展示:

 
5.png

 
 
好了,以上就是全部内容......

参考资料:

在SpringBoot中通过RestTemplate提交文件到Github(白嫖图床)_怎么springboot怎么把图片上传到github里面-CSDN博客
TinyMce富文本处理器 在Vue3 vue-vite中使用(小白避坑 必看)_tinymce vue3-CSDN博客

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册