editor.ui.registry.addIcon(
'fontplus',
`<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 14 14" style="enable-background:new 0 0 14 14;" xml:space="preserve" height="17" width="17">
<rect x="9" y="3" class="st0" width="5" height="1"/>
<rect x="11" y="1" class="st0" width="1" height="5"/>
<g>
<path class="st0" d="M11,13H9.3L8,9.7h-5L1.7,13H0L4.6,1h1.7L11,13z M3.4,8.4h4l-2-5.9L3.4,8.4z"/>
</g>
</svg>
`
)
editor.ui.registry.addIcon(
'fontminus',
`<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 14 14" style="enable-background:new 0 0 14 14;" xml:space="preserve" height="17" width="17">
<rect x="9" y="3" class="st0" width="5" height="1"/>
<g>
<path class="st0" d="M11,13H9.3L8,9.7H3L1.7,13H0L4.6,1h1.7L11,13z M3.4,8.4h4l-2-5.9L3.4,8.4z"/>
</g>
</svg>
`
)
;(function () {
'use strict'
let Tools = tinymce.util.Tools.resolve('tinymce.util.Tools')
let global = tinymce.util.Tools.resolve('tinymce.PluginManager')
let defaults = {
spaces: false,
isInput: !1,
toast: null
}
class WordLimit {
constructor(editor, options) {
this.editor = editor
this.options = Tools.extend(defaults, options)
var _this = this,
oldContent = editor.getContent(),
WordCount = editor.plugins.wordcount,
preCount = 0,
_wordCount = 0
editor.on('input paste undo redo Keyup ', function (e) {
var content = editor.getContent() || e.content || ''
if (!_this.options.spaces) {
_wordCount = WordCount.body.getCharacterCount()
} else {
_wordCount = WordCount.body.getCharacterCountWithoutSpaces()
}
if (_wordCount > _this.options.max) {
preCount = _wordCount
if (_this.options.isInput == !1) {
editor.setContent(oldContent)
if (!_this.options.spaces) {
_wordCount = WordCount.body.getCharacterCount()
} else {
_wordCount = WordCount.body.getCharacterCountWithoutSpaces()
}
}
editor.getBody().blur()
editor.fire('wordlimit', {
maxCount: _this.options.max,
wordCount: _wordCount,
preCount: preCount,
isPaste: e.type === 'paste' || e.paste || false
})
}
oldContent = editor.getContent()
})
}
}
function Plugin() {
global.add('wordlimit', function (editor) {
var options = editor.getParam('wordlimit', {}, 'object')
if (!options && !options.max) {
return !1
}
if (typeof options.toast !== 'function') {
options.toast = function (message) {
editor.notificationManager.open({
text: message,
type: 'error',
timeout: 3000
})
}
}
if (!editor.plugins.wordcount) {
options.toast('请先在tinymce的plugins配置wordlimit之前加入wordcount插件')
return !1
}
editor.on('init', function (e) {
new WordLimit(editor, options)
})
})
}
Plugin()
})()
<script lang="ts" setup>
import { computed, onMounted, onUnmounted } from 'vue'
import tinymce from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/models/dom'
import 'tinymce/themes/silver'
import 'tinymce/icons/default'
import 'tinymce/plugins/wordcount'
import '../../../views/visualization/utils/wordlimit.js'
const props = defineProps({
modelValue: {
type: String,
required: true,
default: ''
},
menubar: {
type: [Boolean, String],
default: 'file edit insert view format table tools help'
},
height: {
type: Number,
default: 600
},
id: {
type: [String, Number],
default: 'myTinymce'
},
disabled: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['update:modelValue', 'getLen'])
let contentValue = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
const initOptions = {
language_url: '/tinymce/langs/zh-Hans.js',
language: 'zh-Hans',
skin_url: '/tinymce/skins/ui/oxide',
content_css: '/tinymce/skins/content/default/content.css ',
content_style:
'::-webkit-scrollbar-thumb:vertical{background-color: #c0c0c0;-webkit-border-radius: 4px;} ::-webkit-scrollbar-track-piece { width: 8px; background-color: transparent; -webkit-border-radius: 4px; } ::-webkit-scrollbar { width: 8px; height: 8px; background-color: transparent; } body{margin:5px 12px} p{font-size:14px;margin-block-start:0;margin-block-end:0; word-wrap: break-word;word-break: break-all;} #tinymce.mce-content-body::before{font-size:14px;color:#b2b2b2}',
height: props.height,
menubar: false,
toolbar: 'forecolor bold FontPlus FontMinus',
plugins: 'wordcount wordlimit',
line_height_formats: '1 1.2 1.4 1.6 2',
font_size_formats: '12px 14px 16px 18px 20px 22px 24px 28px 32px 36px 48px 56px 72px',
placeholder: '在这里输入文字',
branding: false,
statusbar: true,
elementpath: false,
wordlimit: {
spaces: false,
isInput: true
},
setup: function (editor: any) {
editor.ui.registry.addButton('FontPlus', {
icon: 'fontplus',
onAction: function () {
setfontSize(editor, 2)
}
})
editor.ui.registry.addButton('FontMinus', {
icon: 'fontminus',
onAction: function () {
setfontSize(editor, -2)
}
})
editor.ui.registry.addIcon(
'fontplus',
`<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 14 14" style="enable-background:new 0 0 14 14;" xml:space="preserve" height="17" width="17">
<rect x="9" y="3" class="st0" width="5" height="1"/>
<rect x="11" y="1" class="st0" width="1" height="5"/>
<g>
<path class="st0" d="M11,13H9.3L8,9.7h-5L1.7,13H0L4.6,1h1.7L11,13z M3.4,8.4h4l-2-5.9L3.4,8.4z"/>
</g>
</svg>
`
)
editor.ui.registry.addIcon(
'fontminus',
`<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 14 14" style="enable-background:new 0 0 14 14;" xml:space="preserve" height="17" width="17">
<rect x="9" y="3" class="st0" width="5" height="1"/>
<g>
<path class="st0" d="M11,13H9.3L8,9.7H3L1.7,13H0L4.6,1h1.7L11,13z M3.4,8.4h4l-2-5.9L3.4,8.4z"/>
</g>
</svg>
`
)
},
init_instance_callback: (editor) => {
editorRef.value = editor
$(editor.getContainer()).find('button.tox-statusbar__wordcount').click()
editor.on('input', (e) => {
console.log(editor.plugins.wordcount.body.getCharacterCount())
getText(editor)
})
editor.on('paste', (e) => {
getText(editor)
})
editor.on('mouseup', (e) => {
fontSize.value = parseFloat(editor.queryCommandValue('FontSize')) || 14
getText(editor)
})
editor.on('wordlimit', function (e) {
})
}
}
const editorRef = ref()
const tinyID = 'id' + Math.floor(Math.random() * (10000 - 1)) + 1
const initOption = {
selector: tinyID,
language: 'zh_CN',
menubar: false,
toolbar: 'formatting | alignment',
toolbar_groups: {
formatting: {
text: '文字格式',
tooltip: 'Formatting',
items: 'bold italic underline | superscript subscript'
},
alignment: {
icon: 'align-left',
tooltip: 'alignment',
items: 'alignleft aligncenter alignright alignjustify'
}
}
}
onMounted(async () => {
tinymce.init({})
})
onUnmounted(() => {
tinymce.remove()
})
function getText(editor) {
var cnt = editorRef.value.getContent({ format: 'text' })
emit('getLen', editor.plugins.wordcount.body.getCharacterCount())
emit('getRawText', cnt)
}
const fontSize = ref(12)
function setfontSize(editor, change) {
fontSize.value = Number(fontSize.value) + change
if (fontSize.value > 18) {
fontSize.value = 18
}
if (fontSize.value < 12) {
fontSize.value = 12
}
editor.editorCommands.commands.exec.fontsize('fontSize', false, fontSize.value + 'px')
}
</script>
<template>
<div class="tinymce-box">
<Editor v-model="contentValue" :init="initOptions" :id="props.id" :disabled="props.disabled" />
</div>
</template>
<style scoped>
.tinymce-box {
width: 100%;
}
:deep() .tox:not(.tox-tinymce-inline) .tox-editor-header {
padding: 0;
}
:deep() .tox.tox-tinymce {
border-radius: 4px;
border-width: 1px;
border-color: #dcdfe6;
}
:deep() .tox .tox-notifications-container .tox-notification {
display: none;
}
:deep() .tox .tox-listboxfield .tox-listbox--select:focus,
:deep() .tox .tox-textarea:focus,
:deep() .tox .tox-textfield:focus {
border-color: #f60 !important;
}
:deep() .tox .tox-dialog__footer .tox-button {
font-weight: normal;
background-color: #f60 !important;
border-color: #f60 !important;
color: #fff !important;
}
:deep() .tox .tox-dialog__footer .tox-button:hover:not(:disabled) {
color: #fff;
background-color: #ff7214 !important;
border-color: #ff7214 !important;
}
:deep() .tox .tox-dialog__footer .tox-button:active:not(:disabled) {
color: #fff;
background-color: #f06000 !important;
border-color: #f06000 !important;
}
:deep() .tox .tox-tbtn:hover {
background: #f8f8f8;
border: 0;
box-shadow: none;
color: #222f3e;
}
:deep() .tox .tox-tbtn:active,
.tox-tbtn:focus {
background: #e8e8e8;
border: 0;
box-shadow: none;
color: #222f3e;
}
:deep() .tox .tox-tbtn.tox-tbtn--enabled {
background: #e8e8e8;
border: 0;
box-shadow: none;
color: #222f3e;
}
:deep() .tox-tbtn {
}
</style>