富文本 图片(富文本图片上传)

富文本 图片(富文本图片上传)场景系统中经常会用到富文本编辑器 比如新增通知和公告功能 并且需要添加上传图片 vue quill editor 官网 https www npmjs com package vue quill editor 注 博客 https blog csdn net badao liumang qizhi 关注公众号霸道的程序猿获取编程相关电子书 教程推送与免费下载 实现 npm

大家好,我是讯享网,很高兴认识大家。

场景

系统中经常会用到富文本编辑器,比如新增通知和公告功能,并且需要添加上传图片。

Vue中使用vue-quil-editor富文本编辑器+el-upload实现带图片上传到Sprin_java
讯享网

 

vue-quill-editor官网:

https://www.npmjs.com/package/vue-quill-editor

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。

实现
npm install vue-quill-editor –save

讯享网

这里没有使用全局引用,要将这个富文本编辑器做成一个组件,方便引用。

所以在项目下的components下新建Editor目录,在此目录下新建index.vue,用来封装并暴露富文本编辑器组件

引入组件需要添加如下代码,包括ccss文件也是必须要引入的

讯享网import { quillEditor } from ”vue-quill-editor”;import ”quill/dist/quill.core.css”;import ”quill/dist/quill.snow.css”;import ”quill/dist/quill.bubble.css”;

然后在template中添加富文本组件

    &lt;quill-editor      class=“editor”      v-model=“content”      ref=“quillEditor”      :options=“editorOption”      @blur=“onEditorBlur(\(event)"      @focus="onEditorFocus(\)event)“      @change=“onEditorChange(\(event)"    &gt;&lt;/quill-editor&gt;  &lt;/div&gt;</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">设置其菜单栏通过</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">:options="editorOption"</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">对应的菜单栏的内容定义</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">      editorOption: {        placeholder: "",        theme: "snow", // or 'bubble'        placeholder: "请输入内容",        modules: {          toolbar: {            container: toolbarOptions,            handlers: {              image: function(value) {                if (value) {                  // 触发input框选择图片文件                  document.querySelector(".quill-img input").click();                } else {                  this.quill.format("image", false);                }              }            }          }        }      },</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">注意这里的设置img菜单的点击事件会触发一个function</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">在方法中根据class属性找到选择器,此选择器是使用的ElementUI的el-upload,会触发其点击事件</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">el-upload的代码如下</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">    &lt;el-upload      class="avatar-uploader quill-img"      :action="uploadImgUrl"      name="file"      :headers="headers"      :show-file-list="false"      :on-success="quillImgSuccess"      :on-error="uploadError"      :before-upload="quillImgBefore"      accept='.jpg,.jpeg,.png,.gif'    &gt;&lt;/el-upload&gt;</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">使用el-upload进行文件上传到SpringBoot后台并存储到服务器上,以及前端回显照片的路径参照如下博客:</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">继续看富文本组件,其内容的绑定通过</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">v-model="content"</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">来实现,就是组件传递到数据库中存储的内容</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">存储内容示例:</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);"> </p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);"></p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">所以需要提前声明content属性</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">  data() {    return {      content: this.value,</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">并且将当前控件的value赋值给content,因为这里是封装的组件,在调用组件时会将数据库中的数据进行回显</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">&lt;Editor v-model="form.noticeContent" /&gt;</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">然后就能在组件中this.value来获取并赋值给富文本组件绑定的content</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">为了实现监视这两个的改变而改变,所以添加watch函数</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">  watch: {    value: function() {      this.content = this.value;    }  },</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">然后就是设置其一些事件</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">      @blur="onEditorBlur(\)event)“      @focus=“onEditorFocus(\(event)"      @change="onEditorChange(\)event)”

如果需要对这些事件进行操作可在下面进行重写

讯享网    onEditorBlur() {      //失去焦点事件    },    onEditorFocus() {      //获得焦点事件    },    onEditorChange() {      //内容改变事件      this.\(emit("input", this.content);   },</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">上面关联了标题栏中的图片的点击事件会执行el-upload的点击事件。</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">那么在el-upload组件中</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">:action="uploadImgUrl"</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">设置其上传的url</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">:headers="headers"</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">绑定请求头</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">      headers: {        Authorization: 'Bearer ' + getToken()      }</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">请求头里携带token,请求头的设置参考如下</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">再设置它的一些事件</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">      :on-success="quillImgSuccess"      :on-error="uploadError"      :before-upload="quillImgBefore"</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">对上传前,上传成功和失败的事件进行重写</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">    // 富文本图片上传前    quillImgBefore(file) {      let fileType = file.type;   if(fileType === 'image/jpeg' || fileType === 'image/png'){    return true;   }else {    this.\)message.error(‘请插入图片类型文件(jpg/jpeg/png)’);    return false;   }    },     quillImgSuccess(res, file) {      // res为图片服务器返回的数据      // 获取富文本组件实例      let quill = this.\(refs.quillEditor.quill;      // 如果上传成功      if (res.code == 200) {        // 获取光标所在位置        let length = quill.getSelection().index;        // 插入图片  res.url为服务器返回的图片地址        quill.insertEmbed(length, "image", res.url);        // 调整光标到最后        quill.setSelection(length + 1);      } else {        this.\)message.error(“图片插入失败”);      }    },    // 富文本图片上传失败    uploadError() {      // loading动画消失      this.\(message.error("图片插入失败");    }</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">注意这里的图片上传成功是事件中,图片上传对应的后台SpringBoot接口</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">    @PostMapping("/common/upload")    public AjaxResult uploadFile(MultipartFile file) throws Exception {        try {            // 上传文件路径            String filePath = RuoYiConfig.getUploadPath();            // 上传并返回新文件名称            String fileName = FileUploadUtils.upload(filePath, file);            String url = serverConfig.getUrl() + fileName;            AjaxResult ajax = AjaxResult.success();            ajax.put("fileName", fileName);            ajax.put("url", url);            return ajax;        } catch (Exception e) {            return AjaxResult.error(e.getMessage());        }    }</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">在此接口中</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">String filePath = RuoYiConfig.getUploadPath();</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">是在application.yml中获取配置的文件上传的路径</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">然后调用了文件上传工具类的上传方法</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">String fileName = FileUploadUtils.upload(filePath, file);</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">最终后台接口返回的url是一个在服务器上绝对路径的图片地址,比如</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">http://localhost:8080/profile/upload/2020/09/02/e070fd1a26dca6c00acf6db1bc.png</p><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">然后</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">        // 获取光标所在位置        let length = quill.getSelection().index;        // 插入图片  res.url为服务器返回的图片地址        quill.insertEmbed(length, "image", res.url);        // 调整光标到最后        quill.setSelection(length + 1);</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">调用</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">quill.insertEmbed(length, "image", res.url);</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">就能实现在富文本中插入照片,插入成功后的富文本编辑器的内容中就会增加</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">&lt;img src="http://localhost:8080/profile/upload/2020/09/02/e070fd1a26dca6c00acf6db1bc.png "&gt;</pre><p style="margin:0px 0px 16px;padding:0px;max-width:100%;clear:both;min-height:1em;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;font-family:'Microsoft YaHei', 'SF Pro Display', Roboto, Noto, Arial, 'PingFang SC', sans-serif;font-size:18px;color:rgb(77,77,77);line-height:26px;background-color:rgb(255,255,255);">富文本编辑器封装组件的完整代码</p><pre style="margin:0px 0px 24px;padding:8px;max-width:100%;font-style:normal;font-weight:normal;letter-spacing:.544px;text-indent:0px;text-transform:none;word-spacing:0px;font-family:Consolas, Inconsolata, Courier, monospace;white-space:pre-wrap;font-size:14px;line-height:22px;color:rgb(0,0,0);background-color:rgb(255,255,255);">&lt;template&gt;  &lt;div&gt;    &lt;!-- 图片上传组件辅助 --&gt;    &lt;el-upload      class="avatar-uploader quill-img"      :action="uploadImgUrl"      name="file"      :headers="headers"      :show-file-list="false"      :on-success="quillImgSuccess"      :on-error="uploadError"      :before-upload="quillImgBefore"      accept='.jpg,.jpeg,.png,.gif'    &gt;&lt;/el-upload&gt;     &lt;!-- 富文本组件 --&gt;    &lt;quill-editor      class="editor"      v-model="content"      ref="quillEditor"      :options="editorOption"      @blur="onEditorBlur(\)event)“      @focus=“onEditorFocus(\(event)"      @change="onEditorChange(\)event)“    &gt;&lt;/quill-editor&gt;  &lt;/div&gt;&lt;/template&gt; &lt;script&gt;import { getToken } from ’@/utils/auth’ // 工具栏配置const toolbarOptions = [  [“bold”, ”italic”, ”underline”, ”strike”],       // 加粗 斜体 下划线 删除线  [“blockquote”, ”code-block”],                    // 引用  代码块  [{ list: ”ordered” }, { list: ”bullet” }],       // 有序、无序列表  [{ indent: ”-1” }, { indent: ”+1” }],            // 缩进  [{ size: [“small”, false, ”large”, ”huge”] }],   // 字体大小  [{ header: [1, 2, 3, 4, 5, 6, false] }],         // 标题  [{ color: [] }, { background: [] }],             // 字体颜色、字体背景颜色  [{ align: [] }],                                 // 对齐方式  [“clean”],                                       // 清除文本格式  [“link”, ”image”, ”video”]                       // 链接、图片、视频]; import { quillEditor } from ”vue-quill-editor”;import ”quill/dist/quill.core.css”;import ”quill/dist/quill.snow.css”;import ”quill/dist/quill.bubble.css”; export default {  props: {    / 编辑器的内容 /    value: {      type: String    },    / 图片大小 /    maxSize: {      type: Number,      default: 4000 //kb    }  },  components: { quillEditor },  data() {    return {      content: this.value,      uploadImgUrl: ”“,      editorOption: {        placeholder: ”“,        theme: ”snow”, // or ’bubble’        placeholder: ”请输入内容”,        modules: {          toolbar: {            container: toolbarOptions,            handlers: {              image: function(value) {                if (value) {                  // 触发input框选择图片文件                  document.querySelector(“.quill-img input”).click();                } else {                  this.quill.format(“image”, false);                }              }            }          }        }      },      uploadImgUrl: process.env.VUE_APP_BASE_API + ”/common/upload”, // 上传的图片服务器地址      headers: {        Authorization: ’Bearer ’ + getToken()      }    };  },  watch: {    value: function() {      this.content = this.value;    }  },  methods: {    onEditorBlur() {      //失去焦点事件    },    onEditorFocus() {      //获得焦点事件    },    onEditorChange() {      //内容改变事件      this.\(emit("input", this.content);    },     // 富文本图片上传前    quillImgBefore(file) {      let fileType = file.type;   if(fileType === 'image/jpeg' || fileType === 'image/png'){    return true;   }else {    this.\)message.error(‘请插入图片类型文件(jpg/jpeg/png)’);    return false;   }    },     quillImgSuccess(res, file) {      // res为图片服务器返回的数据      // 获取富文本组件实例      let quill = this.\(refs.quillEditor.quill;      // 如果上传成功      if (res.code == 200) {        // 获取光标所在位置        let length = quill.getSelection().index;        // 插入图片  res.url为服务器返回的图片地址        quill.insertEmbed(length, "image", res.url);        // 调整光标到最后        quill.setSelection(length + 1);      } else {        this.\)message.error(“图片插入失败”);      }    },    // 富文本图片上传失败    uploadError() {      // loading动画消失      this.$message.error(“图片插入失败”);    }  }};&lt;/script&gt; &lt;style&gt;.editor {  line-height: normal !important;  height: 192px;}.quill-img {  display: none;}.ql-snow .ql-tooltip[data-mode=“link”]::before {  content: ”请输入链接地址:“;}.ql-snow .ql-tooltip.ql-editing a.ql-action::after {  border-right: 0px;  content: ”保存”;  padding-right: 0px;} .ql-snow .ql-tooltip[data-mode=“video”]::before {  content: ”请输入视频地址:“;} .ql-snow .ql-picker.ql-size .ql-picker-label::before,.ql-snow .ql-picker.ql-size .ql-picker-item::before {  content: ”14px”;}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=“small”]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=“small”]::before {  content: ”10px”;}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=“large”]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=“large”]::before {  content: ”18px”;}.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=“huge”]::before,.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=“huge”]::before {  content: ”32px”;} .ql-snow .ql-picker.ql-header .ql-picker-label::before,.ql-snow .ql-picker.ql-header .ql-picker-item::before {  content: ”文本”;}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=“1”]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=“1”]::before {  content: ”标题1”;}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=“2”]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=“2”]::before {  content: ”标题2”;}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=“3”]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=“3”]::before {  content: ”标题3”;}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=“4”]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=“4”]::before {  content: ”标题4”;}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=“5”]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=“5”]::before {  content: ”标题5”;}.ql-snow .ql-picker.ql-header .ql-picker-label[data-value=“6”]::before,.ql-snow .ql-picker.ql-header .ql-picker-item[data-value=“6”]::before {  content: ”标题6”;} .ql-snow .ql-picker.ql-font .ql-picker-label::before,.ql-snow .ql-picker.ql-font .ql-picker-item::before {  content: ”标准字体”;}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=“serif”]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=“serif”]::before {  content: ”衬线字体”;}.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=“monospace”]::before,.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=“monospace”]::before {  content: ”等宽字体”;}&lt;/style&gt;

封装完组件后就是在需要用到的页面进行引用,比如这里是在通知和公告的新增和编辑页面使用。

来到此vue页面,首先在页面中引入该组件

import Editor from ’@/components/Editor’ ;

然后声明该组件

讯享网export default {  name: ”Notice”,  components: {    Editor  },

此页面为发布通知和公告的页面,所以在新增和编辑时的位置添加该组件

          &lt;el-col :span=“24”&gt;            &lt;el-form-item label=“内容”&gt;              &lt;Editor v-model=“form.noticeContent” /&gt;            &lt;/el-form-item&gt;          &lt;/el-col&gt;

这里的form.noticeContent就是在点击编辑页面时从后台数据库中查询的保存的富文本编辑器的内容。

设计一个公告的数据库,添加存储内容的字段

Vue中使用vue-quil-editor富文本编辑器+el-upload实现带图片上传到Sprin_java_02

 

这样就能实现富文本编辑器的内容的存储和回显以及带照片的上传。



小讯
上一篇 2025-05-26 23:22
下一篇 2025-04-18 17:35

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/143106.html