index.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. <template>
  2. <div :class="{fullscreen:fullscreen}" :style="{width:containerWidth}" class="tinymce-container">
  3. <textarea :id="tinymceId" class="tinymce-textarea" />
  4. <div class="editor-custom-btn-container">
  5. <editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
  6. </div>
  7. </div>
  8. </template>
  9. <script>
  10. import editorImage from './components/EditorImage'
  11. import plugins from './plugins'
  12. import toolbar from './toolbar'
  13. export default {
  14. name: 'Tinymce',
  15. components: { editorImage },
  16. props: {
  17. id: {
  18. type: String,
  19. default: function() {
  20. return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
  21. }
  22. },
  23. value: {
  24. type: String,
  25. default: ''
  26. },
  27. toolbar: {
  28. type: Array,
  29. required: false,
  30. default() {
  31. return []
  32. }
  33. },
  34. height: {
  35. type: [Number, String],
  36. required: false,
  37. default: 360
  38. },
  39. width: {
  40. type: [Number, String],
  41. required: false,
  42. default: 'auto'
  43. }
  44. },
  45. data() {
  46. return {
  47. hasChange: false,
  48. hasInit: false,
  49. tinymceId: this.id,
  50. fullscreen: false
  51. }
  52. },
  53. computed: {
  54. containerWidth() {
  55. const width = this.width
  56. if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
  57. return `${width}px`
  58. }
  59. return width
  60. }
  61. },
  62. watch: {
  63. value(val) {
  64. if (!this.hasChange && this.hasInit) {
  65. this.$nextTick(() =>
  66. window.tinymce.get(this.tinymceId).setContent(val || ''))
  67. }
  68. }
  69. },
  70. mounted() {
  71. this.initTinymce()
  72. },
  73. activated() {
  74. if (window.tinymce) {
  75. this.initTinymce()
  76. }
  77. },
  78. deactivated() {
  79. this.destroyTinymce()
  80. },
  81. destroyed() {
  82. this.destroyTinymce()
  83. },
  84. methods: {
  85. // 初始化
  86. initTinymce() {
  87. const that = this
  88. window.tinymce.init({
  89. selector: `#${this.tinymceId}`,
  90. language: 'zh_CN',
  91. height: this.height,
  92. body_class: 'panel-body ',
  93. object_resizing: false,
  94. toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
  95. external_plugins: {
  96. 'kityformula-editor': '/tinymce/plugins/kityformula-editor/plugin.min.js'
  97. },
  98. menubar: false,
  99. branding: false,
  100. plugins: plugins,
  101. end_container_on_empty_block: true,
  102. powerpaste_word_import: 'clean', // 粘贴时为简洁模式
  103. // powerpaste_word_import: 'propmt', // 粘贴word时 为完整模式
  104. powerpaste_html_import: 'clean', // 粘贴html时, 为完整模式
  105. paste_preprocess: function(plugin, args) {
  106. const re1 = new RegExp('<.+?>', 'g')
  107. args.content = args.content.replace(re1, '')
  108. },
  109. code_dialog_height: 450,
  110. code_dialog_width: 1000,
  111. advlist_bullet_styles: 'square',
  112. advlist_number_styles: 'default',
  113. default_link_target: '_blank',
  114. link_title: false,
  115. wirisformulaeditorlang: 'zh',
  116. nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
  117. init_instance_callback: editor => {
  118. if (that.value) {
  119. editor.setContent(that.value)
  120. }
  121. that.hasInit = true
  122. editor.on('NodeChange Change KeyUp SetContent', () => {
  123. this.hasChange = true
  124. this.$emit('input', editor.getContent())
  125. })
  126. },
  127. setup(editor) {
  128. editor.on('FullscreenStateChanged', (e) => {
  129. that.fullscreen = e.state
  130. })
  131. }
  132. })
  133. },
  134. destroyTinymce() {
  135. const tinymce = window.tinymce.get(this.tinymceId)
  136. if (this.fullscreen) {
  137. tinymce.execCommand('mceFullScreen')
  138. }
  139. if (tinymce) {
  140. tinymce.destroy()
  141. }
  142. },
  143. setContent(value) {
  144. window.tinymce.get(this.tinymceId).setContent(value)
  145. },
  146. getContent() {
  147. window.tinymce.get(this.tinymceId).getContent()
  148. },
  149. getTextContent() {
  150. return window.tinymce.get(this.tinymceId).getContent( { format : 'text' } );
  151. },
  152. imageSuccessCBK(arr) {
  153. const that = this
  154. arr.forEach(v => {
  155. window.tinymce.get(that.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)
  156. })
  157. }
  158. }
  159. }
  160. </script>
  161. <style scoped>
  162. .tinymce-container {
  163. position: relative;
  164. line-height: normal;
  165. }
  166. .editor-custom-btn-container {
  167. position: absolute;
  168. right: 5px;
  169. top: 5px;
  170. z-index: 2005;
  171. }
  172. .fullscreen .editor-custom-btn-container {
  173. z-index: 10000;
  174. position: fixed;
  175. }
  176. .editor-upload-btn {
  177. display: inline-block;
  178. }
  179. </style>