index.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. <template>
  2. <div class="mydiv">
  3. <Editor v-model="contentValue" :init="init" :disabled="disabled" :placeholder="placeholder" @onClick="onClick" />
  4. </div>
  5. </template>
  6. <script setup name="Editor">
  7. import Editor from '@tinymce/tinymce-vue'
  8. import tinymce from 'tinymce/tinymce'
  9. import 'tinymce/themes/silver'
  10. import 'tinymce/icons/default'
  11. import 'tinymce/models/dom'
  12. // 引入编辑器插件
  13. import 'tinymce/plugins/code' // 编辑源码
  14. import 'tinymce/plugins/image' // 插入编辑图片
  15. import 'tinymce/plugins/link' // 超链接
  16. import 'tinymce/plugins/preview' // 预览
  17. import 'tinymce/plugins/table' // 表格
  18. import 'tinymce/plugins/lists' // 列表编号
  19. import 'tinymce/plugins/advlist' //高级列表编号
  20. import 'tinymce/plugins/wordcount' // 字数统计插件
  21. import '@/utils/wordlimit' // 字数插件
  22. const emit = defineEmits(['update:modelValue', 'onClick'])
  23. const props = defineProps({
  24. modelValue: {
  25. type: String,
  26. default: ''
  27. },
  28. placeholder: {
  29. type: String,
  30. default: ''
  31. },
  32. height: {
  33. type: Number,
  34. default: 300
  35. },
  36. disabled: {
  37. type: Boolean,
  38. default: false
  39. },
  40. plugins: {
  41. type: [String, Array],
  42. default: 'code image link preview table lists advlist kityformula-editor wordcount wordlimit'
  43. },
  44. toolbar: {
  45. type: [String, Array],
  46. default:
  47. 'undo redo | forecolor backcolor bold italic underline strikethrough link | blocks fontfamily fontsize | \
  48. alignleft aligncenter alignright alignjustify outdent indent lineheight | bullist numlist | \
  49. image table preview | code selectall'
  50. },
  51. fileUploadFunction: {
  52. type: Function,
  53. default: undefined
  54. }
  55. })
  56. const init = ref({
  57. language_url: '/tinymce/langs/zh_CN.js',
  58. language: 'zh_CN',
  59. skin_url: '/tinymce/skins/ui/oxide',
  60. content_css: '/tinymce/skins/content/default/content.css',
  61. menubar: false,
  62. statusbar: true,
  63. plugins: props.plugins,
  64. toolbar: props.toolbar,
  65. fontsize_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px',
  66. height: props.height,
  67. placeholder: props.placeholder,
  68. branding: false,
  69. resize: true,
  70. elementpath: true,
  71. content_style: '',
  72. toolbar_mode: 'wrap',
  73. wordlimit: {
  74. max: 2147483647
  75. },
  76. external_plugins: {
  77. 'kityformula-editor': '/tinymce/plugins/kityformula-editor/plugin.min.js'
  78. },
  79. automatic_uploads: false,
  80. images_upload_handler(blobInfo, progress) {
  81. return new Promise((resolve, reject) => {
  82. const param = new FormData()
  83. param.append('file', blobInfo.blob(), blobInfo.filename())
  84. props
  85. .fileUploadFunction(param)
  86. .then((data) => {
  87. return resolve(data)
  88. })
  89. .catch((err) => {
  90. return reject('err:' + err)
  91. })
  92. })
  93. },
  94. setup: (editor) => {
  95. editor.on('init', () => {
  96. // getBody().style.fontSize = '14px'
  97. })
  98. editor.ui.registry.addButton('numberedline', {
  99. text: '填空',
  100. onAction: function () {
  101. const count = editor.getBody().querySelectorAll('.gapfilling-span').length
  102. const lineNumber = count + 1
  103. const uuid = 'gapfilling-' + Date.now() + '-' + Math.floor(Math.random() * 10000)
  104. editor.insertContent(
  105. `<span class="gapfilling-span ${uuid}" style="color:red;padding:0 30px;margin:0 5px;border-bottom:3px double red;">${lineNumber}</span>&ZeroWidthSpace;`
  106. )
  107. }
  108. })
  109. }
  110. })
  111. const contentValue = ref(props.modelValue)
  112. watch(props, (newValue) => {
  113. contentValue.value = newValue.modelValue
  114. emit('update:modelValue', newValue.modelValue)
  115. })
  116. watch(contentValue, (newValue) => {
  117. emit('update:modelValue', newValue)
  118. })
  119. const onClick = (e) => {
  120. emit('onClick', e, tinymce)
  121. }
  122. onMounted(() => {
  123. tinymce.init({})
  124. })
  125. </script>
  126. <style scoped>
  127. /* 在el-dialog中tinymce z-index 被太小而被遮挡时要加这两句 */
  128. .tox-tinymce-aux {
  129. z-index: 99999 !important;
  130. }
  131. .tinymce.ui.FloatPanel {
  132. z-index: 99;
  133. }
  134. .mydiv {
  135. :deep(.tox-statusbar__path) {
  136. display: none !important;
  137. }
  138. }
  139. /*.tox .tox-statusbar a, .tox */
  140. </style>