|  |  | 
 |  |  | <template> | 
 |  |  |   <div style="border: 1px solid #ccc;"> | 
 |  |  |   <div class="wang_editor"> | 
 |  |  |     <Toolbar | 
 |  |  |       style="border-bottom: 1px solid #ccc" | 
 |  |  |       :editor="editor" | 
 |  |  |       :defaultConfig="toolbarConfig" | 
 |  |  |       :default-config="toolbarConfig" | 
 |  |  |       :mode="mode" | 
 |  |  |     /> | 
 |  |  |     <Editor | 
 |  |  |       style="height: 300px; overflow-y: hidden;" | 
 |  |  |       :value="content.content" | 
 |  |  |       v-model="html" | 
 |  |  |       style="min-height: 200px" | 
 |  |  |       :default-config="editorConfig" | 
 |  |  |       :mode="mode" | 
 |  |  |       :defaultConfig="editorConfig" | 
 |  |  |       @onCreated="onCreated" | 
 |  |  |       @onChange="onChange" | 
 |  |  |       @input="html=$event" | 
 |  |  |     /> | 
 |  |  |   </div> | 
 |  |  | </template> | 
 |  |  |  | 
 |  |  | <script> | 
 |  |  | import { Editor, Toolbar } from '@wangeditor/editor-for-vue' | 
 |  |  | import '@wangeditor/editor/dist/css/style.css' | 
 |  |  | import axios from 'axios' | 
 |  |  |  | 
 |  |  | import { uploadFile } from '@/api' | 
 |  |  |  | 
 |  |  | const uploadConfig = { | 
 |  |  |   action: uploadFile, // 必填参数 图片上传地址 | 
 |  |  |   methods: 'POST', // 必填参数 图片上传方式 | 
 |  |  |   token: '', // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage | 
 |  |  |   name: 'file', // 必填参数 文件的参数名 | 
 |  |  |   size: 500, // 可选参数   图片大小,单位为Kb, 1M = 1024Kb | 
 |  |  |   accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon' // 可选 可上传的图片格式 | 
 |  |  | } | 
 |  |  | export default { | 
 |  |  |   name: 'RichEditor', | 
 |  |  |   components: { Editor, Toolbar }, | 
 |  |  |   components: { | 
 |  |  |     Editor, | 
 |  |  |     Toolbar | 
 |  |  |   }, | 
 |  |  |   props: { | 
 |  |  |     content: { | 
 |  |  |       type: Object, | 
 |  |  |       default: () => {} | 
 |  |  |     info: { | 
 |  |  |       type: String, | 
 |  |  |       default: '' | 
 |  |  |     }, | 
 |  |  |     default: { | 
 |  |  |       type: String, | 
 |  |  |       default: '' | 
 |  |  |     }, | 
 |  |  |     placeholder: { | 
 |  |  |       type: String, | 
 |  |  |       default: '请输入内容...' | 
 |  |  |     } | 
 |  |  |   }, | 
 |  |  |   data() { | 
 |  |  |   data () { | 
 |  |  |     return { | 
 |  |  |       editor: null, | 
 |  |  |       html: '<p><br></p>', | 
 |  |  |       toolbarConfig: { | 
 |  |  |         toolbarKeys: [ | 
 |  |  |           "headerSelect", | 
 |  |  |           "blockquote", | 
 |  |  |           "|", | 
 |  |  |           "bold", | 
 |  |  |           "underline", | 
 |  |  |           "italic", | 
 |  |  |           { | 
 |  |  |               "key": "group-more-style", | 
 |  |  |               "title": "更多", | 
 |  |  |               "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M204.8 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M505.6 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path><path d=\"M806.4 505.6m-76.8 0a76.8 76.8 0 1 0 153.6 0 76.8 76.8 0 1 0-153.6 0Z\"></path></svg>", | 
 |  |  |               "menuKeys": [ | 
 |  |  |                   "through", | 
 |  |  |                   "code", | 
 |  |  |                   "sup", | 
 |  |  |                   "sub", | 
 |  |  |                   "clearStyle" | 
 |  |  |               ] | 
 |  |  |           }, | 
 |  |  |           "color", | 
 |  |  |           "bgColor", | 
 |  |  |           "|", | 
 |  |  |           "fontSize", | 
 |  |  |           "fontFamily", | 
 |  |  |           "lineHeight", | 
 |  |  |           "|", | 
 |  |  |           "bulletedList", | 
 |  |  |           "numberedList", | 
 |  |  |           "todo", | 
 |  |  |           { | 
 |  |  |               "key": "group-justify", | 
 |  |  |               "title": "对齐", | 
 |  |  |               "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M768 793.6v102.4H51.2v-102.4h716.8z m204.8-230.4v102.4H51.2v-102.4h921.6z m-204.8-230.4v102.4H51.2v-102.4h716.8zM972.8 102.4v102.4H51.2V102.4h921.6z\"></path></svg>", | 
 |  |  |               "menuKeys": [ | 
 |  |  |                   "justifyLeft", | 
 |  |  |                   "justifyRight", | 
 |  |  |                   "justifyCenter", | 
 |  |  |                   "justifyJustify" | 
 |  |  |               ] | 
 |  |  |           }, | 
 |  |  |           { | 
 |  |  |               "key": "group-indent", | 
 |  |  |               "title": "缩进", | 
 |  |  |               "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M0 64h1024v128H0z m384 192h640v128H384z m0 192h640v128H384z m0 192h640v128H384zM0 832h1024v128H0z m0-128V320l256 192z\"></path></svg>", | 
 |  |  |               "menuKeys": [ | 
 |  |  |                   "indent", | 
 |  |  |                   "delIndent" | 
 |  |  |               ] | 
 |  |  |           }, | 
 |  |  |           // "|", | 
 |  |  |           "emotion", | 
 |  |  |           "insertLink", | 
 |  |  |           { | 
 |  |  |               "key": "group-image", | 
 |  |  |               "title": "图片", | 
 |  |  |               "iconSvg": "<svg viewBox=\"0 0 1024 1024\"><path d=\"M959.877 128l0.123 0.123v767.775l-0.123 0.122H64.102l-0.122-0.122V128.123l0.122-0.123h895.775zM960 64H64C28.795 64 0 92.795 0 128v768c0 35.205 28.795 64 64 64h896c35.205 0 64-28.795 64-64V128c0-35.205-28.795-64-64-64zM832 288.01c0 53.023-42.988 96.01-96.01 96.01s-96.01-42.987-96.01-96.01S682.967 192 735.99 192 832 234.988 832 288.01zM896 832H128V704l224.01-384 256 320h64l224.01-192z\"></path></svg>", | 
 |  |  |               "menuKeys": [ | 
 |  |  |                   "insertImage", | 
 |  |  |                   "uploadImage" | 
 |  |  |               ] | 
 |  |  |           }, | 
 |  |  |           "insertTable", | 
 |  |  |           "codeBlock", | 
 |  |  |           "divider", | 
 |  |  |           "|", | 
 |  |  |           "undo", | 
 |  |  |           "redo", | 
 |  |  |           "|", | 
 |  |  |           "fullScreen" | 
 |  |  |         ] | 
 |  |  |       }, | 
 |  |  |       toolbarConfig: {}, | 
 |  |  |       editorConfig: { | 
 |  |  |         placeholder: '请输入内容...', | 
 |  |  |         placeholder: this.placeholder, | 
 |  |  |         MENU_CONF: { | 
 |  |  |           uploadImage: { | 
 |  |  |             // server: '/api/upload', | 
 |  |  |             name: 'file', | 
 |  |  |             server: process.env.VUE_APP_API_PREFIX + '/visitsAdmin/cloudService/public/uploadLocal', | 
 |  |  |             html: this.info, | 
 |  |  |             server: uploadFile, | 
 |  |  |             // 单个文件的最大体积限制,默认为 2M | 
 |  |  |             maxFileSize: 5 * 1024 * 1024, // 1M | 
 |  |  |             // 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 [] | 
 |  |  |             allowedFileTypes: ['image/*'], | 
 |  |  |             // 自定义上传参数,例如传递验证的 token 等。参数会被添加到 formData 中,一起上传到服务端 | 
 |  |  |             meta: { | 
 |  |  |               folder: 'shop' | 
 |  |  |               token: '', | 
 |  |  |               otherKey: '', | 
 |  |  |               folder: 'COURSE_IMG' | 
 |  |  |             }, | 
 |  |  |             onBeforeUpload(file) {    // JS 语法 | 
 |  |  |               // file 选中的文件,格式如 { key: file } | 
 |  |  |               // debugger | 
 |  |  |               return file | 
 |  |  |             // 自定义增加 http  header | 
 |  |  |             headers: { | 
 |  |  |               token: localStorage.getItem('token') || '' | 
 |  |  |               // Accept: 'text/x-json', | 
 |  |  |               // otherKey: 'xxx' | 
 |  |  |             }, | 
 |  |  |             onSuccess(file, res) { | 
 |  |  |                 console.log(`${file.name} 上传成功`, res) | 
 |  |  |             // 跨域是否传递 cookie ,默认为 false | 
 |  |  |             withCredentials: true, | 
 |  |  |             // 超时时间,默认为 10 秒 | 
 |  |  |             timeout: 5 * 1000, // 5 秒 | 
 |  |  |             onSuccess (file, res) { // TS 语法 | 
 |  |  |               // onSuccess(file, res) {          // JS 语法 | 
 |  |  |               console.log(`${file.name} 上传成功`, res) | 
 |  |  |             }, | 
 |  |  |             onError(file, err, res) { | 
 |  |  |               console.log(`${file.name} 上传出错`, err, res) | 
 |  |  |             }, | 
 |  |  |           }, | 
 |  |  |             customUpload (file, insertFn) { // TS 语法 | 
 |  |  |               // file 即选中的文件 | 
 |  |  |               // 自己实现上传,并得到图片 url alt href | 
 |  |  |               // var form = new FormData() | 
 |  |  |               // form.append('image', file) | 
 |  |  |               // form.append('folder', 'COURSE_IMG') | 
 |  |  |               var formData = new FormData() | 
 |  |  |               formData.append(file.name, file) | 
 |  |  |               formData.append('image', file) | 
 |  |  |               formData.append('folder', 'member') | 
 |  |  |               // formData.append('type', '') | 
 |  |  |  | 
 |  |  |               var xhr = new XMLHttpRequest() | 
 |  |  |               xhr.open(uploadConfig.methods, uploadConfig.action, true) | 
 |  |  |               // 上传数据成功,会触发 | 
 |  |  |               xhr.send(formData) | 
 |  |  |               xhr.onreadystatechange = () => { | 
 |  |  |                 // 若响应完成且请求成功 | 
 |  |  |                 if (xhr.readyState === 4 && xhr.status === 200) { | 
 |  |  |                   const result = JSON.parse(xhr.responseText) | 
 |  |  |                   console.log('result', result); | 
 |  |  |                   insertFn(result.data.url, '', result.data.url) | 
 |  |  |                 } | 
 |  |  |               } | 
 |  |  |             }, | 
 |  |  |             customInsert (res, insertFn) { // TS 语法 | 
 |  |  |               // customInsert(res, insertFn) {                  // JS 语法 | 
 |  |  |               // res 即服务端的返回结果 | 
 |  |  |               console.log(res.data.url) | 
 |  |  |               // 从 res 中找到 url alt href ,然后插入图片 | 
 |  |  |               insertFn(res.url) | 
 |  |  |             } | 
 |  |  |           } | 
 |  |  |         } | 
 |  |  |       }, | 
 |  |  |       mode: 'default', // or 'simple' | 
 |  |  |       mode: 'default' // or 'simple' | 
 |  |  |     } | 
 |  |  |   }, | 
 |  |  |   beforeDestroy() { | 
 |  |  |   emits: ['input'], | 
 |  |  |   computed: { | 
 |  |  |     html: { | 
 |  |  |       get () { | 
 |  |  |         return this.info || '' | 
 |  |  |       }, | 
 |  |  |       set (newValue) { | 
 |  |  |         this.$emit('input', newValue) | 
 |  |  |       } | 
 |  |  |     } | 
 |  |  |   }, | 
 |  |  |   mounted () { | 
 |  |  |     setTimeout(() => { | 
 |  |  |       this.info = this.default | 
 |  |  |     }, 1200) | 
 |  |  |   }, | 
 |  |  |   beforeDestroy () { | 
 |  |  |     const editor = this.editor | 
 |  |  |     if (editor == null) return | 
 |  |  |     editor.destroy() // 组件销毁时,及时销毁编辑器 | 
 |  |  |   }, | 
 |  |  |   methods: { | 
 |  |  |     onCreated (editor) { | 
 |  |  |       this.editor = Object.seal(editor) | 
 |  |  |       this.editor = Object.seal(editor) // 一定要用 Object.seal() ,否则会报错 | 
 |  |  |       this.$emit('input', '123123') | 
 |  |  |     }, | 
 |  |  |     onChange (editor) { | 
 |  |  |       console.log(this.html); | 
 |  |  |       // debugger | 
 |  |  |       if (!this.html||this.content.content==this.html) { | 
 |  |  |         return | 
 |  |  |       } | 
 |  |  |       this.$emit('edit', this.html) | 
 |  |  |     }, | 
 |  |  |   }, | 
 |  |  |  | 
 |  |  |     test () { | 
 |  |  |       console.log(this.info) | 
 |  |  |     } | 
 |  |  |   } | 
 |  |  | } | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | <style src="@wangeditor/editor/dist/css/style.css"></style> | 
 |  |  | <style lang="scss" scoped> | 
 |  |  | .wang_editor { | 
 |  |  |   border: 1px solid; | 
 |  |  | } | 
 |  |  | </style> |