作者 RuoYi

Editor组件优化,支持自定义高度&图片冲突问题

1 <template> 1 <template>
2 - <div>  
3 - <!-- 图片上传组件辅助 -->  
4 - <el-upload  
5 - class="avatar-uploader quill-img"  
6 - :action="uploadImgUrl"  
7 - name="file"  
8 - :headers="headers"  
9 - :show-file-list="false"  
10 - :on-success="quillImgSuccess"  
11 - :on-error="uploadError"  
12 - :before-upload="quillImgBefore"  
13 - accept='.jpg,.jpeg,.png,.gif'  
14 - ></el-upload>  
15 -  
16 - <!-- 富文本组件 -->  
17 - <quill-editor  
18 - class="editor"  
19 - v-model="content"  
20 - ref="quillEditor"  
21 - :options="editorOption"  
22 - @blur="onEditorBlur($event)"  
23 - @focus="onEditorFocus($event)"  
24 - @change="onEditorChange($event)"  
25 - ></quill-editor>  
26 - </div> 2 + <div class="editor" ref="editor" :style="styles"></div>
27 </template> 3 </template>
28 4
29 <script> 5 <script>
30 -import { getToken } from '@/utils/auth'  
31 -  
32 -// 工具栏配置  
33 -const toolbarOptions = [  
34 - ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线  
35 - ["blockquote", "code-block"], // 引用 代码块  
36 - [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表  
37 - [{ indent: "-1" }, { indent: "+1" }], // 缩进  
38 - [{ size: ["small", false, "large", "huge"] }], // 字体大小  
39 - [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题  
40 - [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色  
41 - [{ align: [] }], // 对齐方式  
42 - ["clean"], // 清除文本格式  
43 - ["link", "image", "video"] // 链接、图片、视频  
44 -];  
45 -  
46 -import { quillEditor } from "vue-quill-editor"; 6 +import Quill from "quill";
47 import "quill/dist/quill.core.css"; 7 import "quill/dist/quill.core.css";
48 import "quill/dist/quill.snow.css"; 8 import "quill/dist/quill.snow.css";
49 import "quill/dist/quill.bubble.css"; 9 import "quill/dist/quill.bubble.css";
50 10
51 export default { 11 export default {
  12 + name: "Editor",
52 props: { 13 props: {
53 /* 编辑器的内容 */ 14 /* 编辑器的内容 */
54 value: { 15 value: {
55 - type: String 16 + type: String,
  17 + default: "",
  18 + },
  19 + /* 高度 */
  20 + height: {
  21 + type: Number,
  22 + default: null,
56 }, 23 },
57 - /* 图片大小 */  
58 - maxSize: { 24 + /* 最小高度 */
  25 + minHeight: {
59 type: Number, 26 type: Number,
60 - default: 4000 //kb  
61 - } 27 + default: null,
  28 + },
62 }, 29 },
63 - components: { quillEditor },  
64 data() { 30 data() {
65 return { 31 return {
66 - content: this.value,  
67 - uploadImgUrl: "",  
68 - editorOption: {  
69 - theme: "snow", // or 'bubble'  
70 - placeholder: "请输入内容", 32 + Quill: null,
  33 + currentValue: "",
  34 + options: {
  35 + theme: "snow",
  36 + bounds: document.body,
  37 + debug: "warn",
71 modules: { 38 modules: {
72 - toolbar: {  
73 - container: toolbarOptions,  
74 - handlers: {  
75 - image: function(value) {  
76 - if (value) {  
77 - // 触发input框选择图片文件  
78 - document.querySelector(".quill-img input").click();  
79 - } else {  
80 - this.quill.format("image", false);  
81 - }  
82 - }  
83 - }  
84 - }  
85 - } 39 + // 工具栏配置
  40 + toolbar: [
  41 + ["bold", "italic", "underline", "strike"], // 加粗 斜体 下划线 删除线
  42 + ["blockquote", "code-block"], // 引用 代码块
  43 + [{ list: "ordered" }, { list: "bullet" }], // 有序、无序列表
  44 + [{ indent: "-1" }, { indent: "+1" }], // 缩进
  45 + [{ size: ["small", false, "large", "huge"] }], // 字体大小
  46 + [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
  47 + [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
  48 + [{ align: [] }], // 对齐方式
  49 + ["clean"], // 清除文本格式
  50 + ["link", "image", "video"] // 链接、图片、视频
  51 + ],
  52 + },
  53 + placeholder: "请输入内容",
  54 + readOnly: false,
86 }, 55 },
87 - uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址  
88 - headers: {  
89 - Authorization: 'Bearer ' + getToken()  
90 - }  
91 }; 56 };
92 }, 57 },
  58 + computed: {
  59 + styles() {
  60 + let style = {};
  61 + if (this.minHeight) {
  62 + style.minHeight = `${this.minHeight}px`;
  63 + }
  64 + if (this.height) {
  65 + style.height = `${this.height}px`;
  66 + }
  67 + return style;
  68 + },
  69 + },
93 watch: { 70 watch: {
94 - value: function() {  
95 - this.content = this.value;  
96 - } 71 + value: {
  72 + handler(val) {
  73 + if (val !== this.currentValue) {
  74 + this.currentValue = val;
  75 + if (this.Quill) {
  76 + this.Quill.pasteHTML(this.value);
  77 + }
  78 + }
  79 + },
  80 + immediate: true,
  81 + },
  82 + },
  83 + mounted() {
  84 + this.init();
  85 + },
  86 + beforeDestroy() {
  87 + this.Quill = null;
97 }, 88 },
98 methods: { 89 methods: {
99 - onEditorBlur() {  
100 - //失去焦点事件  
101 - },  
102 - onEditorFocus() {  
103 - //获得焦点事件 90 + init() {
  91 + const editor = this.$refs.editor;
  92 + this.Quill = new Quill(editor, this.options);
  93 + this.Quill.pasteHTML(this.currentValue);
  94 + this.Quill.on("text-change", (delta, oldDelta, source) => {
  95 + const html = this.$refs.editor.children[0].innerHTML;
  96 + const text = this.Quill.getText();
  97 + const quill = this.Quill;
  98 + this.currentValue = html;
  99 + this.$emit("input", html);
  100 + this.$emit("on-change", { html, text, quill });
  101 + });
  102 + this.Quill.on("text-change", (delta, oldDelta, source) => {
  103 + this.$emit("on-text-change", delta, oldDelta, source);
  104 + });
  105 + this.Quill.on("selection-change", (range, oldRange, source) => {
  106 + this.$emit("on-selection-change", range, oldRange, source);
  107 + });
  108 + this.Quill.on("editor-change", (eventName, ...args) => {
  109 + this.$emit("on-editor-change", eventName, ...args);
  110 + });
104 }, 111 },
105 - onEditorChange() {  
106 - //内容改变事件  
107 - this.$emit("input", this.content);  
108 - },  
109 -  
110 - // 富文本图片上传前  
111 - quillImgBefore(file) {  
112 - let fileType = file.type;  
113 - if(fileType === 'image/jpeg' || fileType === 'image/png'){  
114 - return true;  
115 - }else {  
116 - this.$message.error('请插入图片类型文件(jpg/jpeg/png)');  
117 - return false;  
118 - }  
119 - },  
120 -  
121 - quillImgSuccess(res, file) {  
122 - // res为图片服务器返回的数据  
123 - // 获取富文本组件实例  
124 - let quill = this.$refs.quillEditor.quill;  
125 - // 如果上传成功  
126 - if (res.code == 200) {  
127 - // 获取光标所在位置  
128 - let length = quill.getSelection().index;  
129 - // 插入图片 res.url为服务器返回的图片地址  
130 - quill.insertEmbed(length, "image", res.url);  
131 - // 调整光标到最后  
132 - quill.setSelection(length + 1);  
133 - } else {  
134 - this.$message.error("图片插入失败");  
135 - }  
136 - },  
137 - // 富文本图片上传失败  
138 - uploadError() {  
139 - // loading动画消失  
140 - this.$message.error("图片插入失败");  
141 - }  
142 - } 112 + },
143 }; 113 };
144 -</script> 114 +</script>
145 115
146 <style> 116 <style>
147 .editor { 117 .editor {
148 white-space: pre-wrap!important; 118 white-space: pre-wrap!important;
149 line-height: normal !important; 119 line-height: normal !important;
150 - height: 192px;  
151 } 120 }
152 .quill-img { 121 .quill-img {
153 display: none; 122 display: none;
@@ -159,12 +159,12 @@ @@ -159,12 +159,12 @@
159 </el-col> 159 </el-col>
160 <el-col :span="24"> 160 <el-col :span="24">
161 <el-form-item label="内容"> 161 <el-form-item label="内容">
162 - <Editor v-model="form.noticeContent" /> 162 + <editor v-model="form.noticeContent" :min-height="192"/>
163 </el-form-item> 163 </el-form-item>
164 </el-col> 164 </el-col>
165 </el-row> 165 </el-row>
166 </el-form> 166 </el-form>
167 - <div slot="footer" class="dialog-footer" style="padding-top:30px"> 167 + <div slot="footer" class="dialog-footer">
168 <el-button type="primary" @click="submitForm">确 定</el-button> 168 <el-button type="primary" @click="submitForm">确 定</el-button>
169 <el-button @click="cancel">取 消</el-button> 169 <el-button @click="cancel">取 消</el-button>
170 </div> 170 </div>