<template> <div class="quill-editor" :style="{'background': mode !== 'display' && isShowDom ? '#f1f1f1' : '#fff'}"> <!-- v-show="mode === 'display' || !isShowDom" --> <div style="min-height: 200px;" ref="editor"></div> <!-- <div v-show="mode !== 'display' && isShowDom" class="my-editor-wrap"> <div id="my-quill-editor"></div> </div> --> </div> </template> <script> import Vue from 'vue/dist/vue.esm.js' import {cloneDeep} from 'lodash' import Quill from "quill"; const defaultOptions = { theme: "snow", boundary: document.body, modules: { toolbar: [ ["bold", "italic", "underline", "strike"], ["blockquote", "code-block"], // [{ header: 1 }, { header: 2 }], // [{ list: "ordered" }, { list: "bullet" }], // [{ script: "sub" }, { script: "super" }], [{ indent: "-1" }, { indent: "+1" }], // [{ direction: "rtl" }], [{ size: ["small", false, "large", "huge"] }], // [{ header: [1, 2, 3, 4, 5, 6, false] }], // [{ color: [] }, { background: [] }], // [{ font: [] }], [{ align: [] }], ["clean"], ["custom-btn"], // ["link", "image", "video"], ], }, // placeholder: "Insert text here ...", readOnly: false, }; export default { name: "RichTextEditor", props: { content: String, value: String, isShowDom: { type: Boolean, default: false, }, model: { type: Object, default: () => {}, }, disabled: { type: Boolean, default: false, }, options: { type: Object, required: false, default: () => ({}), }, placeholder: { type: String, required: false, default: "Insert text here ...", }, insertParams: { type: Object, default: () => { return { isShowInsertFn: false, width: '52px', btnText: '插入业务变量', insertContent: '' } } }, gidtxtMarkText: { type: String, default: '' }, templateList: { type: Array, default: () => [] }, // 重置问题 isReset: { type: Boolean, default: false }, gtxgidtxtMark: { type: String, default: '' } }, data() { return { _options: {}, _content: "", defaultOptions, timer: null }; }, computed: { mode() { return this.$store.state.Status.mode; }, isDisable: { get() { return this.mode === "display" || this.disabled; }, }, }, mounted() { this.initialize(); }, beforeDestroy() { this.quill = null; delete this.quill; }, methods: { isInModel (model, code) { let isIn = true if (code) { let codeList = code.split('.') let curProp = null let tempObj = cloneDeep(model) if (codeList && codeList.length > 0) { while (curProp = codeList.shift()) { if (tempObj[curProp] === undefined) { isIn = false break; } else { tempObj = tempObj[curProp] } } } } return isIn }, customComponent (list) { let tem = this.gidtxtMarkText list.map((item) => { if (tem.indexOf(`{${item.cod}}`) > -1) { if (item.showflg === 'Y') { tem = tem.replace(`{${item.cod}}`, `{{model.textTempData.${item.cod}}}`) } else { let code = `${item.path.split('\\').join('.').toLowerCase()}` let isIn = this.isInModel(this.model, code) if (isIn) { let modelPath = `{{model.${item.path.split('\\').join('.').toLowerCase()}}}` tem = tem.replace(`{${item.cod}}`, modelPath) } } } }) console.log('tem======', tem) let Profile = Vue.extend({ template: '<div class="my-quill-editor-content">' + tem + '</div>', props: ['model'], updated: () => { if (this.timer) { clearTimeout(this.timer) this.timer = null } if (this.isShowDom){ this.timer = setTimeout(() => { this.$emit('input', document.querySelector('.my-quill-editor-content').innerHTML) }, 1000) } } }) let divDom = '<div id="my-id"></div>' document.querySelector('#my-quill-editor').innerHTML = divDom new Profile({ propsData: { model: this.model } }).$mount(document.querySelector('#my-quill-editor').querySelector('#my-id')) this.$emit('input', document.querySelector('.my-quill-editor-content').innerHTML) }, initialize() { if (this.$el) { // Options this._options = Object.assign( { placeholder: this.placeholder }, this.defaultOptions, this.options ); this.quill = new Quill(this.$refs.editor, this._options); // 自定义添加工具栏按钮 if (this.insertParams.isShowInsertFn) { this.addCustomDom() } this.quill.enable(false); if (this.value || this.content) { this.quill.pasteHTML(this.value || this.content); } if (!this.isDisable) { this.quill.enable(true); } this.quill.on("selection-change", (range) => { if (!range) { this.$emit("blur", this.quill); } else { this.$emit("focus", this.quill); } }); // 更新 this.quill.on("text-change", (delta, oldDelta, source) => { let html = this.$refs.editor.children[0].innerHTML; const quill = this.quill; const text = this.quill.getText(); let formatHtml = html.replace('<br>', '<br/>') // if (html === "<p><br/></p>") html = ""; this._content = formatHtml; this.$emit("input", this._content); this.$emit("change", { formatHtml, text, quill }); }); this.$emit("ready", this.quill); } }, addCustomDom () { let customDom = document.querySelector('.ql-custom-btn') customDom.style.background = '#f2f2f2' customDom.style.borderRadius = '6px' customDom.style.width = this.insertParams.width customDom.innerText = this.insertParams.btnText console.log('添加插入工具按钮成功:', this.insertParams) customDom.addEventListener('click', this.handleClickCustomDom) }, // 点击插入按钮,插入对应内容 handleClickCustomDom () { if (this.disabled) { return; } const range = this.quill.getSelection(); console.log('插入内容成功:', this.insertParams.insertContent) if (range) { this.quill.insertText(range.index, this.insertParams.insertContent); } } }, watch: { isReset: { handler (newVal) { if (newVal) { this.quill.pasteHTML(this.gtxgidtxtMark) this.$emit("ready", this.quill); this.$emit('input', this.gtxgidtxtMark) } } }, templateList: { handler (newVal) { if (newVal && newVal.length > 0 && this.gidtxtMarkText) { this.customComponent(newVal) } }, deep: true }, gidtxtMarkText: { handler (newVal) { if (newVal && this.templateList && this.templateList.length > 0) { this.customComponent(this.templateList) } }, deep: true }, content(newVal, oldVal) { if (this.quill) { if (newVal && newVal !== this._content) { this._content = newVal; this.quill.pasteHTML(newVal); } else if (!newVal) { this.quill.setText(""); } } }, value: { handler (newVal, oldVal) { if (this.quill) { if (newVal && newVal !== this._content) { this._content = newVal; this.quill.pasteHTML(newVal); } else if (!newVal) { this.quill.setText(""); } } }, deep: true }, isDisable(newVal, oldVal) { if (this.quill) { this.quill.enable(!newVal); } }, }, beforeDestroy () { let customDom = document.querySelector('.ql-custom-btn') if (customDom) { customDom.removeEventListener('click', this.handleClickCustomDom) } } }; </script> <style scoped lang="less"> .ql-toolbar.ql-snow .ql-formats { line-height: 1; } .ql-editor { min-height: 200px; max-height: 500px; } .my-editor-wrap { width: 100%; overflow: auto; border-right: 1px solid #ccc; border-left: 1px solid #ccc; border-bottom: 1px solid #ccc; padding: 10px; min-height: 200px; } </style>