1.其实element-admin中已经整合了tinyMce 富文本的配置,可是再项目需求中须要本身上传本地图片,就像这样(用霉霉来镇楼)html
2.本次项目上传图片的思想:先拿到本地的图片转换为base64 的格式,传递给后端,后端保存后再返回给咱们一个图片地址,最终咱们须要的就是这个地址作显示和保存vue
具体的操做:由于安装和基本的富文本配置都由elementui +admin 给咱们作了,我这里主要是再贴一些本次我用到的工具和配置web
1)plugins:后端
const plugins= ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount ']
2)工具条 toolbarapi
const toolbar = ['searchreplace fontselect formatselect fontsizeselect bold italic underline strikethrough forecolor backcolor', ' hr alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscriptcode codesample bullist numlist ', ' table link image charmap preview anchor pagebreak insertdatetime media emoticons fullscreen ']
3)最后全部的配置,和图片的上传app
export default { name: 'Tinymce', // components: { editorImage }, props: { id: { type: String, default: function () { return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '') } }, value: { type: String, default: '' }, config: { type: Object, default: () => { return { theme: 'modern', height: 400 } } }, toolbar: { type: Array, required: false, default () { return [] } }, accept: { default: 'image/jpeg, image/png', type: String }, url: { default: '', type: String }, maxSize: { default: 2097152, type: Number }, withCredentials: { default: false, type: Boolean }, menubar: { type: String, default: 'file edit insert view format table' }, height: { type: [Number, String], required: false, default: 360 }, width: { type: [Number, String], required: false, default: 'auto' } }, data () { return { Value: '', Url: '', upLoadBaseURL: 'process.env.VUE_APP_BASE_API', hasChange: false, hasInit: false, tinymceId: this.id, fullscreen: false, languageTypeList: { 'zh': 'zh_CN', 'en': 'en', 'es': 'es_MX', 'ja': 'ja' }, api: { uploadImage: "/api/imageUpload" }, } }, computed: { containerWidth () { const width = this.width if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'` return `${width}px` } return width } }, watch: { value (val) { if (!this.hasChange && this.hasInit) { this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val || '')) } } }, mounted () { this.init() }, activated () { if (window.tinymce) { this.initTinymce() } }, deactivated () { this.destroyTinymce() }, destroyed () { this.destroyTinymce() }, methods: { init () { // dynamic load tinymce from cdn load(tinymceCDN, (err) => { if (err) { this.$message.error(err.message) return } this.initTinymce() }) }, initTinymce () { // const _this = this const _this = this window.tinymce.init({ selector: `#${this.tinymceId}`, language: this.languageTypeList['zh'], height: this.height, body_class: 'panel-body ', object_resizing: false, toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar, menubar: this.menubar, plugins: plugins, end_container_on_empty_block: true, powerpaste_word_import: 'clean', code_dialog_height: 450, code_dialog_width: 1000, advlist_bullet_styles: 'square', advlist_number_styles: 'default', imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'], default_link_target: '_blank', link_title: false, // CONFIG: Paste 粘贴 paste_retain_style_properties: 'all', paste_word_valid_elements: '*[*]', // word须要它 paste_data_images: true, // 粘贴的同时能把内容里的图片自动上传,很是强力的功能 paste_convert_word_fake_lists: false, // 插入word文档须要该属性 paste_webkit_styles: 'all', paste_merge_formats: true, nonbreaking_force_tab: false, paste_auto_cleanup_on_paste: false, // CONFIG: ContentStyle 这块很重要, 在最后呈现的页面也要写入这个基本样式保证先后一致, `table`和`img`的问题基本就靠这个来填坑了 content_style: ` * { padding:0; margin:0; } html, body { height:100%; } img { max-width:100%; display:block;height:auto; } a { text-decoration: none; } iframe { width: 100%; } p { line-height:1.6; margin: 0px; } table { word-wrap:break-word; word-break:break-all; max-width:100%; border:none; border-color:#999; } .mce-object-iframe { width:100%; box-sizing:border-box; margin:0; padding:0; } ul,ol { list-style-position:inside; } `, insert_button_items: 'image link | inserttable', // CONFIG: StyleSelect style_formats: [ { title: '首行缩进', block: 'p', styles: { 'text-indent': '2em' } }, { title: '行高', items: [ { title: '1', styles: { 'line-height': '1' }, inline: 'span' }, { title: '1.5', styles: { 'line-height': '1.5' }, inline: 'span' }, { title: '2', styles: { 'line-height': '2' }, inline: 'span' }, { title: '2.5', styles: { 'line-height': '2.5' }, inline: 'span' }, { title: '3', styles: { 'line-height': '3' }, inline: 'span' } ] } ], // FontSelect font_formats: ` 微软雅黑=微软雅黑; 宋体=宋体; 黑体=黑体; 仿宋=仿宋; 楷体=楷体; 隶书=隶书; 幼圆=幼圆; Andale Mono=andale mono,times; Arial=arial, helvetica, sans-serif; Arial Black=arial black, avant garde; Book Antiqua=book antiqua,palatino; Comic Sans MS=comic sans ms,sans-serif; Courier New=courier new,courier; Georgia=georgia,palatino; Helvetica=helvetica; Impact=impact,chicago; Symbol=symbol; Tahoma=tahoma,arial,helvetica,sans-serif; Terminal=terminal,monaco; Times New Roman=times new roman,times; Trebuchet MS=trebuchet ms,geneva; Verdana=verdana,geneva; Webdings=webdings; Wingdings=wingdings,zapf dingbats`, // Tab tabfocus_elements: ':prev,:next', object_resizing: true, // Image imagetools_toolbar: 'rotateleft rotateright | flipv fliph | editimage imageoptions', nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin init_instance_callback: editor => { if (_this.value) { editor.setContent(_this.value) } _this.hasInit = true editor.on('NodeChange Change KeyUp SetContent', () => { this.hasChange = true this.$emit('input', editor.getContent()) }) }, setup (editor) { //自定义功能 editor.on('FullscreenStateChanged', (e) => { _this.fullscreen = e.state }) }, // ....上传图片配置代码 images_upload_handler: (blobInfo, success, failure) => { var reader = new FileReader(); reader.readAsDataURL(blobInfo.blob()); reader.onload = function () { raceApi.postImgUrl({ image: this.result }).then(res => { //这里就是要上传base64 格式的图片的请求了 if (res.code == 200) { let url = res.data.domain + res.data.path success(url) console.log(url); } }) } }, // prop内传入的的config ...this.config, content_style: 'img {max-width:100% !important }', // 初始化赋值 这个主要是防止图片拉升变形的 (上传的图片再app显示会变形要加上这个) setup: (editor) => { // 抛出 'on-ready' 事件钩子 editor.on( 'init', () => { _this.loading = false _this.$emit('on-ready') editor.setContent(_this.value) } ) // 抛出 'input' 事件钩子,同步value数据 editor.on( 'input change undo redo', () => { _this.$emit('input', editor.getContent()) } ) } }) }, destroyTinymce () { const tinymce = window.tinymce.get(this.tinymceId) if (this.fullscreen) { tinymce.execCommand('mceFullScreen') } if (tinymce) { tinymce.destroy() } }, setContent (value) { window.tinymce.get(this.tinymceId).setContent(value) }, getContent () { window.tinymce.get(this.tinymceId).getContent() }, imageSuccessCBK (arr) { const _this = this arr.forEach(v => { window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`) }) } } } `