Last active
May 18, 2025 19:03
-
-
Save mouyong/16467a10a52b91cec814e260e1e9c29b to your computer and use it in GitHub Desktop.
vue3 版本的 135 编辑器集成,参考:https://gist.github.com/mouyong/f3838ffdf827021e47506810d4c17ffc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <VueMarkdownEditor | |
| v-model="newModelValue" | |
| :disabled-menus="[]" | |
| :include-level="[1, 2, 3, 4, 5, 6]" | |
| @upload-image="handleUploadImage" | |
| @change="change" | |
| :height="height + 'px'" | |
| :placeholder="placeholder" | |
| > | |
| </VueMarkdownEditor> | |
| </template> | |
| <script setup lang="ts"> | |
| import { computed } from 'vue'; | |
| import VueMarkdownEditor from '@kangc/v-md-editor'; | |
| import '@kangc/v-md-editor/lib/style/base-editor.css'; | |
| import vuepressTheme from '@kangc/v-md-editor/lib/theme/vuepress.js'; | |
| import '@kangc/v-md-editor/lib/theme/style/vuepress.css'; | |
| import Prism from 'prismjs'; | |
| import { getCurrentInstance } from 'vue'; | |
| const { proxy } = getCurrentInstance(); | |
| if (!(window as any).__V_MARKDOWN_EDITOR_THEME_REGISTERED__) { | |
| VueMarkdownEditor.use(vuepressTheme, { Prism }); | |
| (window as any).__V_MARKDOWN_EDITOR_THEME_REGISTERED__ = true; | |
| } | |
| interface Props { | |
| modelValue?: string; | |
| placeholder?: string; | |
| height?: number; | |
| type?: string; | |
| usageType?: string; | |
| uploadFile?: Function; | |
| } | |
| const props = withDefaults(defineProps<Props>(), { | |
| type: 'image', | |
| placeholder: '', | |
| usageType: '', | |
| height: 300, | |
| }); | |
| const emit = defineEmits(['update:modelValue', 'htmlContent']); | |
| const newModelValue = computed({ | |
| get() { | |
| return props.modelValue; | |
| }, | |
| set(value: string) { | |
| emit('update:modelValue', value); | |
| }, | |
| }); | |
| const change = (markdownContent: any, htmlContent: any) => { | |
| emit('update:modelValue', markdownContent); | |
| emit('htmlContent', htmlContent); | |
| }; | |
| const handleUploadImage = async ( | |
| event: any, | |
| insertImage: (info: { url: string; desc?: string }) => void, | |
| files: File[], | |
| ) => { | |
| console.log(files); | |
| const file = files[0]; | |
| if (!file) return; | |
| const toBase64 = (file: File): Promise<string> => { | |
| return new Promise((resolve, reject) => { | |
| const reader = new FileReader(); | |
| reader.readAsDataURL(file); // 读取为 base64 | |
| reader.onload = () => resolve(reader.result as string); | |
| reader.onerror = (error) => reject(error); | |
| }); | |
| }; | |
| const toBlobUrl = (file: File): Promise<string> => { | |
| return new Promise((resolve, reject) => { | |
| const blobUrl = URL.createObjectURL(file); | |
| return blobUrl; | |
| }); | |
| }; | |
| const data = new FormData(); | |
| data.append('file', file, file.name); // 直接用 File | |
| data.append('type', props.type); | |
| data.append('usage_type', props.usageType); | |
| window.file = file as any; | |
| console.log(window.file, '上传文件信息'); | |
| let url = ''; | |
| try { | |
| let res: any = null; | |
| if (props.uploadFile) { | |
| res = await props.uploadFile(data); // 你自定义的上传接口 | |
| } | |
| console.log(res); | |
| if (!res || !res.data?.fileinfo?.url) { | |
| throw new Error('上传失败'); | |
| } | |
| url = res.data?.fileinfo?.url; | |
| } catch (err) { | |
| console.error(err, '上传文件失败'); | |
| url = await toBase64(file); | |
| } | |
| insertImage({ | |
| url, | |
| desc: file.name, | |
| }); | |
| }; | |
| </script> | |
| <style></style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <EditorMD | |
| v-if="content_type === 'markdown'" | |
| v-bind="{ ...$props, content_type: undefined }" | |
| :uploadFile="uploadFile" | |
| @update:modelValue="(value: any) => emit('update:modelValue', value)" | |
| /> | |
| <TinyMCE | |
| v-if="content_type === 'rich_text'" | |
| v-bind="{ ...$props, content_type: undefined }" | |
| :uploadFile="uploadFile" | |
| @update:modelValue="(value: any) => emit('update:modelValue', value)" | |
| /> | |
| </template> | |
| <script setup lang="ts" name="MyEditor"> | |
| import { withDefaults } from 'vue'; | |
| import { uploadFile } from '../MyUpload/api'; | |
| import EditorMD from './EditorMD.vue'; | |
| import TinyMCE from './TinyMCE.vue'; | |
| interface Props { | |
| modelValue?: string; | |
| placeholder?: string; | |
| height?: number; | |
| type?: string; | |
| usageType?: string; | |
| uploadFile?: Function; | |
| // export const CONTENT_TYPE_OPTIONS = [ | |
| // { label: t('pages.memoryRecognitionKnowledge.content_type_enums.rich_text'), value: 'rich_text' }, | |
| // { label: t('pages.memoryRecognitionKnowledge.content_type_enums.markdown'), value: 'markdown' }, | |
| // ]; | |
| // <t-col :span="8"> | |
| // <t-form-item :label="$t('pages.memoryRecognitionKnowledge.formBase.content_type')" name="content_type"> | |
| // <t-radio-group | |
| // v-model="formData.content_type" | |
| // :default-value="'rich_text'" | |
| // name="mode" | |
| // :options="CONTENT_TYPE_OPTIONS" | |
| // @change="() => {}" | |
| // > | |
| // </t-radio-group> | |
| // </t-form-item> | |
| // </t-col> | |
| content_type?: string; // rich_text, markdown | |
| } | |
| const props = withDefaults(defineProps<Props>(), { | |
| content_type: 'rich_text', | |
| }); | |
| const emit = defineEmits(['update:modelValue']); | |
| </script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| tinymce.PluginManager.add('editor135', function (editor, url) { | |
| let activeEditor = null; // 用于保存当前活动的 tinymce 编辑器实例 | |
| let iframeSrc = '' | |
| const openDialog = function (editor) { | |
| // iframeSrc = 'https://www.135editor.com/simple_editor.html?callback=true&appkey=' + '&editorId=' + editor.id; // 无免费样式过滤操作 | |
| iframeSrc = 'https://www.135editor.com/beautify_editor.html?callback=true&appkey=' + '&editorId=' + editor.id; // 有免费样式过滤操作 | |
| activeEditor = editor; | |
| // return window.open(iframeSrc, '_blank'); // 需要注释这行,注释后可避免原有文章内容无法同步的问题 | |
| return editor.windowManager.openUrl({ | |
| title: '135编辑器', | |
| url: iframeSrc, | |
| size: 'large', | |
| }); | |
| }; | |
| // 接收135传来的数据 | |
| window.addEventListener('message', function (event) { | |
| if (event.origin !== 'https://www.135editor.com') { | |
| return false; | |
| } | |
| if (typeof event.data !== 'string') { | |
| if (event.data.ready) { | |
| console.log('135加载完成'); | |
| // 获取135实例 | |
| const editor135 = document.querySelector(`iframe[src='${iframeSrc}']`); | |
| if (editor135) { | |
| editor135.contentWindow.postMessage(editor.getContent(), '*'); | |
| } | |
| } | |
| return; | |
| }; | |
| if (activeEditor) { | |
| // 使用 activeEditor 变量来访问当前活动的 tinymce 编辑器实例 | |
| activeEditor.setContent(event.data); | |
| activeEditor.windowManager.close(); | |
| activeEditor = null; // 重置 activeEditor 变量以防止后续的错误处理 | |
| } | |
| }, false); | |
| editor.ui.registry.getAll().icons.editor135 || editor.ui.registry.addIcon('editor135', | |
| '<svg t="1609988577378" class="icon" viewBox="0 0 1375 1024" width="22" height="22" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="811" width="200" height="200"><path d="M1118.988883 1021.363716h-1013.760512l-6.082563-50.688026c32.947217-244.823164 17.740809-490.153208 8.110084-735.990131 57.277469-117.596219-3.548162-136.857669-101.376051-123.678783 8.110084-43.591702-35.988498-112.020537 68.428835-101.376051 128.747585 10.644485 258.508931 0 387.763396 0-101.376051 193.628258 101.376051 113.034297 152.064076 167.777365v216.944749c-80.593961-15.206408-192.107617-118.60998-202.752102 70.456356-25.344013 155.612239 117.596219 121.144381 189.066335 167.270484l10.644486 226.068594c-44.605463-11.658246-86.169644-57.277469-134.830148-22.302731-11.658246 8.110084-12.165126 58.291229-7.603204 59.81187 50.688026 17.740809 91.745326 117.596219 156.119119 20.782091l95.293488 5.068802c83.128362-117.089339 32.440336-246.850685 35.481618-371.543227v-17.740809c-6.589443-124.185663 53.729307-253.440128-43.084822-370.022587l-50.688026-6.082563L561.420602 7.603204c228.096115 0 456.19223 16.727048 683.781465-5.575683 160.681041-16.220168 124.692543 74.004517 127.226944 157.63976a324.910244 324.910244 0 0 1-210.862186 47.139863c0-37.509139 22.809612-84.649003-43.591702-88.704044h-57.277469l-86.169644 44.098582c-90.731566 96.814129-79.5802 197.6833-11.151365 300.579992l13.685767-4.561923c57.277469 91.238446 164.229203 105.937973 245.836924 159.667281 2.534401 50.688026 5.575683 103.910452 8.110084 156.119119-54.743068 62.346271-241.781882-175.380569-206.807145 90.731566-31.426576 90.224686 70.456356 99.85541 94.786608 156.625999z" fill="#F9FAF8" p-id="812"></path><path d="M1161.566825 206.807144a324.910244 324.910244 0 0 0 210.862186-47.139863v405.504204a119.62374 119.62374 0 0 1-46.126103-6.082563c-105.937973-94.786608-286.894225-141.926472-220.492911-346.199214z" fill="#FBFAF6" p-id="813"></path><path d="M99.145808 970.67569l6.082563 50.688026c-50.688026-4.055042-109.993016 27.878414-104.924213-76.032039 11.151366-210.862186 3.548162-422.231253 3.548162-633.60032h50.688026c27.878414 216.94475-53.729307 443.520224 44.605462 658.944333z" fill="#10A4E3" p-id="814"></path><path d="M561.420602 7.603204c32.947217 50.688026 66.401314 97.321009 101.376051 146.488394l-50.688026 21.288971c-50.688026-54.743068-253.440128 25.850893-152.064076-167.777365z" fill="#E6430F" p-id="815"></path><path d="M1326.302908 559.088922a119.62374 119.62374 0 0 0 46.126103 6.082563v50.688026c-74.511398 55.249948-39.02978 136.857669-50.688025 207.314025l-90.731566-50.688026c-2.534401-50.688026-5.575683-103.910452-8.616964-156.119119z" fill="#E75225" p-id="816"></path><path d="M1321.740986 823.173536c11.658246-70.456356-23.823372-152.064077 50.688025-207.314025v354.816179l-50.688025 50.688026h-50.688026a311.224477 311.224477 0 0 0-6.082563-43.591702z" fill="#EC774C" p-id="817"></path><path d="M1264.970397 977.772014a311.224477 311.224477 0 0 1 6.082563 43.591702h-152.064077c-24.330252-56.770589-126.213184-66.401314-94.786608-157.13288z" fill="#008FFE" p-id="818"></path><path d="M54.540346 311.731357l-23.823372 3.548162H6.386721v-202.752102c101.376051-13.178887 160.681041 6.082563 101.376052 123.678782z" fill="#CDC04C" p-id="819"></path><path d="M1321.740986 1021.363716l50.688025-50.688026c9.630725 43.591702-7.096324 60.31875-50.688025 50.688026z" fill="#EEBEAB" p-id="820"></path><path d="M1264.970397 977.772014l-240.768122-113.541178c-34.974738-266.112134 152.064077-28.385294 206.807145-90.731565l90.731566 50.688025c-18.754569 50.688026-38.016019 101.882931-56.770589 153.584718z" fill="#E6BC2A" p-id="821"></path><path d="M1326.302908 559.088922l-105.937973 56.770589c-81.100841-53.729307-188.052575-68.428835-245.330044-159.667281 152.064077-35.988498 73.497637-161.187921 97.321009-247.357565h31.426576c-64.373793 208.327785 116.582459 254.960769 222.520432 350.254257z" fill="#FDB41A" p-id="822"></path><path d="M612.108627 175.380569l50.688026-21.288971 50.688026 6.082563 6.082563 304.128153-95.800369 101.376052-14.699527-57.277469 4.561922-117.089339z" fill="#89AD17" p-id="823"></path><path d="M54.540346 311.731357l55.249948-77.552679c9.630725 245.836924 24.837133 491.166968-8.110084 735.990132-100.869171-214.917229-19.26145-441.492703-47.139864-658.437453z" fill="#008EDD" p-id="824"></path><path d="M1074.383421 210.355306c-23.823372 86.169644 50.688026 211.369067-97.321009 247.357565l-13.685767 4.561922c3.548162-101.376051 7.096324-202.752102 11.151365-300.579991l86.676524-44.098583a160.174161 160.174161 0 0 0 8.616965 41.057301z" fill="#E4500E" p-id="825"></path><path d="M720.074122 919.987665l-95.293488-5.068803-13.685767-58.291229-10.644486-226.068595a59.81187 59.81187 0 0 1 21.288971-19.261449l94.279728 13.178886z" fill="#A8BF10" p-id="826"></path><path d="M612.108627 392.325318l-4.561922 117.089339-198.19018-45.619223c11.658246-190.080096 123.171902-86.676524 202.752102-71.470116z" fill="#FEE404" p-id="827"></path><path d="M409.356525 463.795434l197.17642 46.632984c5.068803 18.754569 9.630725 38.016019 14.699527 57.277469a213.903468 213.903468 0 0 0 0 44.098582 59.81187 59.81187 0 0 0-21.288971 19.26145c-70.963236-47.139864-213.903468-12.672006-190.586976-167.270485z" fill="#E1B007" p-id="828"></path><path d="M719.060361 463.795434l-6.082563-304.128153c96.814129 114.048058 36.495378 245.836924 43.084822 370.022586-12.165126-20.78209-24.837133-42.071061-37.002259-65.894433zM720.074122 919.987665c0-98.33477 0-196.669539-3.548162-295.51119 12.672006-25.344013 25.850893-50.688026 39.02978-76.032038-3.041282 124.185663 47.646744 253.947008-35.481618 371.543228zM974.52801 159.667281c-4.055042 101.376051-7.603204 202.752102-11.151365 300.579991-68.428835-100.869171-79.5802-199.203941 11.151365-300.579991z" fill="#FBFAF6" p-id="829"></path><path d="M612.108627 856.120752l13.685767 58.29123c-64.373793 96.814129-106.444854-3.041282-156.119119-20.782091-4.561922 0-4.055042-50.688026 7.603204-59.81187 47.646744-34.974738 89.210925 10.644485 134.830148 22.302731z" fill="#0899E8" p-id="830"></path><path d="M755.55574 547.937557c-13.178887 25.344013-26.357773 50.688026-39.02978 76.032038l-94.786608-13.178887a213.903468 213.903468 0 0 1 0-44.098582l95.800369-101.376051c12.165126 21.795851 24.837133 43.084822 37.002258 64.373792z" fill="#3A7B00" p-id="831"></path><path d="M1074.383421 210.355306l-4.561922-50.688025 50.688025-40.550421c66.401314 4.055042 45.112343 50.688026 43.591702 88.704045l-55.756828 6.082563h-15.713288z" fill="#8FB01C" p-id="832"></path><path d="M1118.988883 118.1031l-50.688025 40.55042a160.174161 160.174161 0 0 1-8.616965-41.057301z" fill="#7EC21E" p-id="833"></path></svg>' | |
| ); | |
| // 注册一个工具栏按钮名称 | |
| editor.ui.registry.addButton('editor135', { | |
| // text: '135', | |
| icon: 'editor135', | |
| tooltip: '使用135编辑器', | |
| onAction: function () { | |
| openDialog(editor); | |
| } | |
| }); | |
| // 注册一个菜单项名称 menu/menubar | |
| editor.ui.registry.addMenuItem('editor135', { | |
| text: '135编辑器', | |
| icon: 'editor135', | |
| onAction: function () { | |
| openDialog(editor); | |
| } | |
| }); | |
| return { | |
| getMetadata: function () { | |
| return { | |
| // 插件名和链接会显示在“帮助”→“插件”→“已安装的插件”中 | |
| name: "135编辑器", //插件名称 | |
| url: "https://marketplace.plugins-world.cn", //作者网址 | |
| }; | |
| } | |
| }; | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <Editor | |
| v-model="formData.table_prefix_post_description" | |
| :content_type="formData.content_type" | |
| usageType="table_prefix_post_description" | |
| :uploadFile="uploadFile" | |
| :height="500" | |
| :placeholder="$t('projectForm.placeholder.table_prefix_post_description')" | |
| /> | |
| </template> | |
| <script lang="ts" setup> | |
| import { ref } from 'vue'; | |
| // 替换成项目的上传接口 | |
| import { uploadFile } from '@/api/global'; | |
| const formData = ref({ | |
| table_prefix_post_description: '' | |
| }); | |
| </script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <div ref="editor"></div> | |
| </template> | |
| <script setup lang="ts" name="TinyMCE"> | |
| import { ref, watch, onMounted, onUnmounted, withDefaults } from 'vue'; | |
| import tinymce from 'tinymce'; | |
| interface Props { | |
| modelValue?: string; | |
| placeholder?: string; | |
| height?: number; | |
| type?: string; | |
| usageType?: string; | |
| uploadFile?: Function; // 项目的上传接口 | |
| } | |
| const props = withDefaults(defineProps<Props>(), { | |
| type: 'image', | |
| placeholder: '', | |
| usageType: '', | |
| height: 300, | |
| }); | |
| const editor = ref<HTMLElement | null>(null); | |
| const editorInstance = ref<tinymce.Editor | null>(null); | |
| const emitModelValue = defineEmits(['update:modelValue']); | |
| onMounted(() => { | |
| tinymce.init({ | |
| target: editor.value as HTMLElement, | |
| license_key: 'gpl', | |
| base_url: '/tinymce', | |
| external_plugins: { | |
| editor135: '/tinymce/plugins/editor135/plugin.js', | |
| preview: '/tinymce/plugins/preview/plugin.js', | |
| fullscreen: '/tinymce/plugins/fullscreen/plugin.js', | |
| autosave: '/tinymce/plugins/autosave/plugin.js', | |
| // importword: '/tinymce/plugins/importword/plugin.js', // https://github.com/Five-great/tinymce-plugins/blob/main/importword/plugin.js | |
| // tpImportword: '/tinymce/plugins/tpImportword/plugin.js', // https://github.com/tinymce-plugin/tinymce-plugin/blob/main/tpImportword/plugin.js | |
| // tpImportword: 'https://unpkg.com/[email protected]/plugins/tpImportword/plugin.min.js', // https://github.com/tinymce-plugin/tinymce-plugin/blob/main/tpImportword/plugin.js | |
| link: '/tinymce/plugins/link/plugin.js', | |
| lists: '/tinymce/plugins/lists/plugin.js', | |
| pagebreak: '/tinymce/plugins/pagebreak/plugin.js', | |
| image: '/tinymce/plugins/image/plugin.js', | |
| media: '/tinymce/plugins/media/plugin.js', | |
| table: '/tinymce/plugins/table/plugin.js', | |
| wordcount: '/tinymce/plugins/wordcount/plugin.js', | |
| code: '/tinymce/plugins/code/plugin.js', | |
| codesample: '/tinymce/plugins/codesample/plugin.js', | |
| }, | |
| language_url: '/tinymce/langs/zh_CN.js', | |
| language: 'zh_CN', | |
| skin_url: '/tinymce/skins/ui/oxide', | |
| content_css: '/tinymce/skins/content/default/content.css', | |
| menubar: false, | |
| statusbar: true, | |
| plugins: [], | |
| skeletonScreen: true, | |
| toolbar: `editor135 preview print fullscreen restoredraft tpImportword | undo redo | forecolor backcolor bold italic underline strikethrough link | blocks fontfamily fontsize | \ | |
| alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | pagebreak | \ | |
| image media table wordcount | code codesample selectall`, | |
| autosave_ask_before_unload: true, | |
| autosave_interval: '10s', | |
| toolbar_mode: 'sliding', | |
| font_size_formats: '12px 14px 16px 18px 22px 24px 36px 72px', | |
| height: props.height, | |
| placeholder: props.placeholder || '', | |
| branding: false, | |
| resize: true, | |
| elementpath: true, | |
| content_style: '', | |
| quickbars_selection_toolbar: 'forecolor backcolor bold italic underline strikethrough link', | |
| quickbars_image_toolbar: 'alignleft aligncenter alignright', | |
| quickbars_insert_toolbar: false, | |
| image_caption: true, | |
| image_advtab: true, | |
| images_upload_handler(blobInfo: any) { | |
| const toBase64 = (file: File): Promise<string> => { | |
| return new Promise((resolve, reject) => { | |
| const reader = new FileReader(); | |
| reader.readAsDataURL(file); // 读取为 base64 | |
| reader.onload = () => resolve(reader.result as string); | |
| reader.onerror = (error) => reject(error); | |
| }); | |
| }; | |
| const toBlobUrl = (file: File): Promise<string> => { | |
| return Promise.resolve(URL.createObjectURL(file)); | |
| }; | |
| return new Promise(async (resolve, reject) => { | |
| // 声明上传参数 | |
| const data = new FormData(); | |
| data.append('file', blobInfo.blob(), blobInfo.filename()); | |
| data.append('type', props.type); | |
| data.append('usage_type', props.usageType); | |
| window.blobInfo = blobInfo as any; | |
| console.log(window.blobInfo, '上传文件信息'); | |
| try { | |
| let res: any = null; | |
| if (props.uploadFile) { | |
| res = await props.uploadFile(data); // 你自定义的上传接口 | |
| } | |
| console.log(res); | |
| const url = res?.data?.fileinfo?.url; | |
| if (!url) throw new Error('上传失败'); | |
| // TinyMCE 要求返回 string url | |
| resolve(url); | |
| } catch (err) { | |
| console.error('上传失败,尝试使用 base64 显示', err); | |
| try { | |
| const base64 = await toBase64(blobInfo.blob()); | |
| resolve(base64); | |
| } catch (e) { | |
| reject(new Error('图片上传失败,且 base64 解析失败')); | |
| } | |
| } | |
| }); | |
| }, | |
| setup(tinymceEditor: any) { | |
| editorInstance.value = tinymceEditor; | |
| tinymceEditor.on('init', () => { | |
| tinymceEditor.getBody().style.fontSize = '14px'; | |
| // 避免 props.modelValue 还没有值就执行了 | |
| setTimeout(() => { | |
| tinymceEditor.setContent(props.modelValue || ''); | |
| }, 1500); | |
| const container = tinymceEditor.getContainer(); | |
| const wordCountButton = container.querySelector('button.tox-statusbar__wordcount'); | |
| wordCountButton?.click(); | |
| }); | |
| tinymceEditor.on('change undo redo', () => { | |
| emitModelValue('update:modelValue', tinymceEditor.getContent()); | |
| }); | |
| tinymceEditor.on('OpenWindow', (e) => { | |
| // FIX 编辑器在el-drawer中,编辑器的弹框无法获得焦点 | |
| const D = document.querySelector('.el-drawer.open'); | |
| const E = e.target.editorContainer; | |
| if (D && D.contains(E)) { | |
| const nowDA = document.activeElement; | |
| setTimeout(() => { | |
| document.activeElement.blur(); | |
| nowDA.focus(); | |
| }, 0); | |
| } | |
| }); | |
| }, | |
| }); | |
| }); | |
| watch( | |
| () => props.modelValue, | |
| (newVal: any) => { | |
| if (editorInstance.value && newVal !== editorInstance.value.getContent()) { | |
| editorInstance.value.setContent(newVal || ''); | |
| } | |
| }, | |
| ); | |
| // Cleanup editor instance on component unmount | |
| onUnmounted(() => { | |
| if (editorInstance.value) { | |
| tinymce.remove(editorInstance.value); | |
| } | |
| }); | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
icons、plugins、skins、themes 从 node_modules 复制到 public/tinymce/ 目录
langs 从官网下载 https://www.tiny.cloud/get-tiny/language-packages/