123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- <template>
- <div class="tinymce-editor">
- <textarea :id="id" style="visibility:hidden;"></textarea>
- </div>
- </template>
- <script>
- // Use self-hosted TinyMCE
- const loadTinyMCE = () => {
- if (window.tinymce) return Promise.resolve(window.tinymce)
-
- return new Promise((resolve, reject) => {
- const script = document.createElement('script')
- script.src = '/static/tinymce/tinymce.min.js'
- script.onload = () => {
- if (window.tinymce) {
- resolve(window.tinymce)
- } else {
- reject(new Error('Failed to load TinyMCE'))
- }
- }
- script.onerror = reject
- document.head.appendChild(script)
- })
- }
- export default {
- name: 'TinymceEditor',
- props: {
- value: {
- type: String,
- default: ''
- },
- init: {
- type: Object,
- default: () => ({})
- },
- placeholder: {
- type: String,
- default: ''
- }
- },
- data() {
- return {
- id: 'tinymce-' + Date.now() + Math.floor(Math.random() * 1000),
- editor: null,
- hasChange: false
- }
- },
- watch: {
- value(val) {
- if (!this.hasChange && this.editor) {
- this.editor.setContent(val)
- }
- }
- },
- mounted() {
- this.initEditor()
- },
- beforeDestroy() {
- if (this.editor) {
- this.editor.destroy()
- }
- },
- methods: {
- async initEditor() {
- try {
- const tinymce = await loadTinyMCE()
-
- const config = {
- selector: `#${this.id}`,
- language_url: this.init.language_url || '/static/tinymce/zh_CN.js',
- language: this.init.language || 'zh_CN',
- height: this.init.height || 300,
- plugins: this.init.plugins || 'link lists image code table wordcount',
- toolbar: this.init.toolbar || 'undo redo | formatselect | bold italic | alignleft aligncenter alignright | bullist numlist outdent indent | link image | code',
- images_upload_handler: this.init.images_upload_handler || null,
- placeholder: this.placeholder,
- skin_url: '/static/tinymce/skins/ui/oxide',
- content_css: '/static/tinymce/skins/content/default/content.css',
- setup: editor => {
- editor.on('init', () => {
- editor.setContent(this.value)
- })
- editor.on('change keyup', () => {
- this.hasChange = true
- this.$emit('input', editor.getContent())
- })
- }
- }
- tinymce.init(config).then(editors => {
- this.editor = editors[0]
- }).catch(error => {
- console.error('TinyMCE init error:', error)
- this.$message.error('富文本编辑器初始化失败')
- })
- } catch (error) {
- console.error('Failed to load TinyMCE:', error)
- this.$message.error('加载富文本编辑器失败')
- }
- }
- }
- }
- </script>
- <style>
- .tox-tinymce {
- border-radius: 4px;
- border: 1px solid #dcdfe6 !important;
- }
- </style>
|