踩过好多坑,以前的教程有些写法是旧的,现在引用的是新的,
比如
quill.getSelection() 现在要写成
quill.selection.savedRange.index;
首先由于多个页面需要用到,故全局在main.js引入
import VueQuillEditor from 'vue-quill-editor' import 'quill/dist/quill.core.css' import 'quill/dist/quill.snow.css' import 'quill/dist/quill.bubble.css' Vue.use(VueQuillEditor)
在需要的页面引入,由于要上传后台,所以借助el-upload触发上传事件
<div> <template> <el-upload class="avatar-uploader" v-show="false" :http-request="upload" name="img" :show-file-list="false" :on-success="uploadSuccess" :before-upload="beforeUpload"> </el-upload> <quill-editor v-model="dataForm.taskRemark" ref="editor" :options="editorOption" ></quill-editor> </template> </div>
自定义工具栏
import 'quill/dist/quill.snow.css' const toolbarOptions = [ ['image'] ]
data () { return { editorOption: { // ... 其他Quill配置 ... modules: { toolbar: { container: toolbarOptions, // 工具栏 handlers: { 'image': function(value) { if (value) { // alert('点击了上传图片') // 调用element的图片上传组件 document.querySelector('.avatar-uploader input').click() } else { this.quill.format('image', false); } } }, clipboard: { matchers: [ // ['img', (node, delta) => this.handlePasteImg(node, delta)] ['img', this.handlePasteImg] ], // 是否允许粘贴 allowSelection: true, // 粘贴前是否清理剪贴板内容 cleanPaste: true }, } }, placeholder: '输入内容...' },
}
}
自定义一个粘贴监听事件
mounted() { // 自定义粘贴图片功能 let quill = this.$refs.editor.quill if (!this.disableFlag) { toolbarOptions[0] = ['image'] } this.$forceUpdate() quill.root.addEventListener('paste', evt => { console.log('addEventListener(\'paste\'') if (evt.clipboardData && evt.clipboardData.files && evt.clipboardData.files.length) { evt.preventDefault(); [].forEach.call(evt.clipboardData.files, file => { if (!file.type.match(/^image\/(gif|jpe?g|a?png|bmp)/i)) { return } console.log(file) console.log('addEventListener(\'image\'') // let file = _self.dataURLtoFile(base64code, 'paste.png'); // 2.2 var fd = new FormData(); fd.append('image',file); this.uploadImage(fd) // this.uploadToServer(file, (res) => { // // 获取光标内容 // var range = quill.getSelection() // if (range) { // this.uploadAttachment(res, file, null) // // 将光标移动到图片后面 // this.$refs.myQuillEditor.quill.setSelection(range.index + 1) // } // }) }) } }, false) },
图片文件上传到后台的方法
uploadImage (fd) { // var fd = new FormData(); // fd.append('image',param.file); this.$http({ url: this.$http.adornUrl(`/XXX/upImageXXXX`), method: 'post', headers:{ 'Content-type': 'multipart/form-data' }, data: fd }).then(({data}) => { if (data && data.code === 0) { console.log('okok') console.log(data) var newUrl = data.data.url // newUrl = "https://ebui-cdn.bj.bcebos.com/yiyan-logo.png" // https://ebui-cdn.bj.bcebos.com/yiyan-logo.png // this.$refs.editor.quill.insertEmbed(cursorLocation,"image",newUrl); // resetUploader(); let quill = this.$refs.editor.quill // 如果上传成功 if (data && data.code === 0) { // 获取光标所在位置 let length = quill.selection.savedRange.index; // 插入图片,res为服务器返回的图片链接地址 console.log(data.data.url) quill.insertEmbed(length, 'image', newUrl) // 调整光标到最后 quill.setSelection(length + 1) } else { // 提示信息,需引入Message this.$message.error('图片插入失败!') } console.log(this.content) } else { this.$message.error(data.msg) // resetUploader(); } }) },
后台处理方法
@ResponseBody @RequestMapping("/upImageXXXX") public R upImageXXXX(MultipartFile image) { String filePath = fileRoot; String suffix = ""; try { String originalFilename = image.getOriginalFilename(); if (originalFilename.contains(".")) { suffix = originalFilename.substring(originalFilename.lastIndexOf(".")); } String uuid = UUID.randomUUID().toString().replace("-", "").toUpperCase(); String fileName = uuid + suffix; File targetFile = new File(filePath, fileName); if(!targetFile.exists()){ targetFile.createNewFile(); } try { image.transferTo(targetFile); } finally { } // String url=urlPrefix + "/richTextFile/downImage/" + fileName; String url=urlPrefix + "/richTextFile/downImage/" + fileName; JSONObject jsonObject1=new JSONObject(); jsonObject1.put("url",url); return R.ok().put("data",jsonObject1); } catch (Exception e) { return R.error(e.getMessage()); } }
另一个访问URL去下载或者显示
@RequestMapping("/downImage/{name}") public void downImage(@PathVariable String name, HttpServletRequest req, HttpServletResponse resp) throws IOException { String path= fileRoot + "/" + name; FileUpOrDownLoadUtils.downOneFile(fullPath, fileName, req, resp);
FileInputStream fs = new FileInputStream(path); resp.reset(); resp.setContentType("application/octet-stream"); resp.addHeader("Content-Disposition","attachment;filename=" + URLEncoder.encode(name,"UTF-8")); resp.addHeader("Access-Control-Allow-Origin",req.getHeader("origin")); resp.addHeader("Access-Control-Allow-Credentials","true"); resp.addHeader("Access-Control-Expose-Headers","Cst-File-Name");// 设置额外暴露的响应头 resp.addHeader("Cst-File-Name",URLEncoder.encode(name,"UTF-8")); // 将文件名存放到响应头 ServletOutputStream os = resp.getOutputStream(); byte[]b = new byte[1024]; int len; while((len=fs.read(b))>0){ os.write(b,0,len); } fs.close();
}