1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
| <template> <div class="tinymce-container" :class="{fullscreen: fullscreen}" :style="{width: containerWidth}"> <editor :id="id" :ref="id" v-model="content" :init="initOptions" /> </div> </template>
<script lang="ts"> import { Component, Prop, Vue } from 'vue-property-decorator'
// Docs: https://www.tiny.cloud/docs/advanced/usage-with-module-loaders/ // Import TinyMCE import 'tinymce/tinymce' // Default icons are required for TinyMCE 5.3 or above import 'tinymce/icons/default' // Import themes import 'tinymce/themes/silver' import 'tinymce/themes/mobile' // Any plugins you want to use has to be imported import 'tinymce/plugins/advlist' import 'tinymce/plugins/anchor' import 'tinymce/plugins/autolink' import 'tinymce/plugins/autosave' import 'tinymce/plugins/code' import 'tinymce/plugins/codesample' import 'tinymce/plugins/directionality' import 'tinymce/plugins/emoticons' import 'tinymce/plugins/fullscreen' import 'tinymce/plugins/hr' import 'tinymce/plugins/image' import 'tinymce/plugins/imagetools' import 'tinymce/plugins/insertdatetime' import 'tinymce/plugins/link' import 'tinymce/plugins/lists' import 'tinymce/plugins/media' import 'tinymce/plugins/nonbreaking' import 'tinymce/plugins/noneditable' import 'tinymce/plugins/pagebreak' import 'tinymce/plugins/paste' import 'tinymce/plugins/preview' import 'tinymce/plugins/print' import 'tinymce/plugins/save' import 'tinymce/plugins/searchreplace' import 'tinymce/plugins/spellchecker' import 'tinymce/plugins/tabfocus' import 'tinymce/plugins/table' import 'tinymce/plugins/template' import 'tinymce/plugins/textpattern' import 'tinymce/plugins/visualblocks' import 'tinymce/plugins/visualchars' import 'tinymce/plugins/wordcount'
import Editor from '@tinymce/tinymce-vue'
@Component({ name: 'TinymceEditor', components: { Editor } }) export default class extends Vue { // 传入的富文本字符串 @Prop({ default: '' }) value!: string @Prop({ default: `${+new Date()}` }) private id!: string @Prop({ default: '360px' }) private height!: string | number @Prop({ default: 'auto' }) private width!: string | number
private hasChange = false private hasInit = false private fullscreen = false
// 富文本框值 get content() { return this.value }
// 监听值改变并$emit,同@input监听 set content(content) { this.$emit('input', content) }
get containerWidth() { const width = this.width // Test matches `100`, `'100'` if (/^[\d]+(\.[\d]+)?$/.test(width.toString())) { return `${width}px` } return width }
// 富文本框init配置 private get initOptions() { return { selector: ` height: this.height, body_class: 'tinymce-body ', // 富文本body上增加class language: 'zh_CN', language_url: `${process.env.BASE_URL}tinymce/langs/zh_CN.js`, // process.env.BASE_URL指向public路径 skin_url: `${process.env.BASE_URL}tinymce/skins/ui/oxide`, emoticons_database_url: `${process.env.BASE_URL}tinymce/emojis.min.js`, menubar: 'file edit insert view format table tools help', // true, false, or string of menus plugins: ['advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textpattern visualblocks visualchars wordcount'], // 插件 toolbar: ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote hr pagebreak subscript superscript removeformat emoticons link image media charmap anchor bullist numlist insertdatetime table forecolor backcolor', '| fontselect | fontsizeselect | formatselect | code codesample | undo redo | preview fullscreen'], // 工具条 font_formats: '微软雅黑=Microsoft Yahei; Arial=arial,helvetica,sans-serif; 宋体=SimSun; Impact=impact,chicago;', // 字体 fontsize_formats: '11px 12px 14px 16px 18px 24px 36px 48px 64px 72px', // 文字大小 codesample_languages: [ { text: 'HTML/XML', value: 'markup' }, { text: 'JavaScript', value: 'javascript' }, { text: 'CSS', value: 'css' }, { text: 'Java', value: 'java' }, { text: 'C++', value: 'cpp' } ], object_resizing: false, 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', default_link_target: '_blank', link_title: false, nonbreaking_force_tab: true, convert_urls: false, branding: false, paste_data_images: true, // 图片上传回调 images_upload_handler: (blobInfo: any, success: any) => { const file = blobInfo.blob() console.log(file) // this.$api.common.aliyunUpload(file, 'donggu').then((url: any) => { // success(url) // }) }, // 初始化回调 init_instance_callback: (editor: any) => { 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: any) => { editor.on('FullscreenStateChanged', (e: any) => { this.fullscreen = e.state }) } } } } </script>
<style lang="scss" scoped></style>
|