<template> <div class="quill" ref="quill" :class="classes"> <div ref="editor" :style="styles" v-loading="loading"></div> <el-upload :headers="headers" :action="this.api.fileupload" :before-upload="beforeUpload" :on-success="editorUploadSuccess" style="display: none" > <el-button class="editorUpload" type="primary">点击上传</el-button> </el-upload> </div> </template> <script> import util from "@/libs/util"; import Setting from "@/setting"; import Quill from "quill"; import "quill/dist/quill.core.css"; import "quill/dist/quill.snow.css"; import "quill/dist/quill.bubble.css"; import toolbarOptions from "./options"; export default { name: "quill", props: { value: { type: String, default: "" }, readonly: { type: Boolean, default: false }, toTop: { type: Boolean, default: true }, border: { type: Boolean, default: false }, height: { type: Number }, minHeight: { type: Number }, /* * 原本的readOnly失效,对比其他项目,发现是quill版本不同导致, * 使用props传入elseRead = 'true',手动隐藏工具栏 */ elseRead: { type: String, default: "false" } }, data() { return { headers: { token: util.local.get(Setting.tokenKey) }, Quill: null, currentValue: "", options: { theme: "snow", bounds: document.body, debug: "warn", modules: { toolbar: { container: toolbarOptions, handlers: { "image": function(value) { if (value) { // 调用iview图片上传 document.querySelector(".editorUpload").click(); } else { this.Quill.format("image", false); } } } } }, placeholder: "", readOnly: this.readonly }, loading: false }; }, computed: { classes() { return [ { "quill-no-border": !this.border } ]; }, styles() { let style = {}; if (this.minHeight) { style.minHeight = `${this.minHeight}px`; } if (this.height) { style.height = `${this.height}px`; } return style; } }, watch: { value: { handler(val) { if (val !== this.currentValue) { this.currentValue = val; if (this.Quill) { this.Quill.pasteHTML(this.value); } } }, immediate: true } }, created() { }, mounted() { this.init(); // 处理工具栏隐藏样式 if (this.elseRead === "true") { let children = this.$refs.quill.children[0].style; children.padding = "0"; children.overflow = "hidden"; children.height = "0"; children.borderTop = "0"; } }, beforeDestroy() { // 在组件销毁后销毁实例 this.Quill = null; }, methods: { init() { const editor = this.$refs.editor; // 初始化编辑器 this.Quill = new Quill(editor, this.options); // 默认值 this.Quill.pasteHTML(this.currentValue); if (this.toTop) { this.$nextTick(() => { window.scrollTo(0, 0); }); } // 绑定事件 this.Quill.on("text-change", (delta, oldDelta, source) => { const html = this.$refs.editor.children[0].innerHTML; const text = this.Quill.getText(); const quill = this.Quill; // 更新内部的值 this.currentValue = html; // 发出事件 v-model this.$emit("input", html); // 发出事件 this.$emit("on-change", { html, text, quill }); }); // 将一些 quill 自带的事件传递出去 this.Quill.on("text-change", (delta, oldDelta, source) => { this.$emit("on-text-change", delta, oldDelta, source); }); this.Quill.on("selection-change", (range, oldRange, source) => { this.$emit("on-selection-change", range, oldRange, source); }); this.Quill.on("editor-change", (eventName, ...args) => { this.$emit("on-editor-change", eventName, ...args); }); }, beforeUpload(file) { this.loading = true; }, editorUploadSuccess(res) { // 获取富文本组件实例 let quill = this.Quill; // 如果上传成功 if (res.data.filesResult.fileUrl) { // 获取光标所在位置 let length = quill.getSelection().index; // 插入图片,res为服务器返回的图片链接地址 quill.insertEmbed(length, "image", res.data.filesResult.fileUrl); // 调整光标到最后 quill.setSelection(length + 1); } else { util.successMsg("图片插入失败"); } this.loading = false; } } }; </script> <style lang="scss" scoped> .quill-no-border { .ql-toolbar.ql-snow { border: none; border-bottom: 1px solid #e8eaec; } .ql-container.ql-snow { border: none; } } .else { .ql-toolbar.ql-snow { height: 0; overflow: hidden; padding: 0; border-top: 0; } } </style>