相關(guān)包
"tinymce": "^6.3.1"
"@tinymce/tinymce-vue": "^5.0.0"
"element-plus": "^2.2.28"
復制icons寨昙、skins
安裝完成后页慷,在 public文件夾 下創(chuàng)建 tinymce文件夾察郁,然后在node_modules下找到 tinymce待逞,注意不是 @tinymce,復制 icons垦搬、skins 文件夾到 public/tinymce6 下
下載中文語言包
下載地址:https://www.tiny.cloud/get-tiny/language-packages/呼寸,下載 zh_CN,下載后猴贰,把解壓后的 langs文件夾 放到 public/tinymce6 下
組件代碼
<template>
<div>
<Editor v-model="myValue" :init="init" :disabled="disabled"/>
<input type="file" hidden :id="id" :accept="imgAccept"/>
<div class="oe-editor-del-btn" v-if="showDel">
<img src="../assets/img/editor_del.png" alt="">
</div>
</div>
</template>
<script lang="ts" setup>
import {computed, onMounted, reactive, ref} from "vue"
import tinymce from 'tinymce/tinymce'
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver/theme'
import 'tinymce/icons/default'
import 'tinymce/models/dom'
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/autolink'
import 'tinymce/plugins/lists'
import 'tinymce/plugins/link'
import 'tinymce/plugins/image'
import 'tinymce/plugins/charmap'
import 'tinymce/plugins/preview'
import 'tinymce/plugins/anchor'
import 'tinymce/plugins/searchreplace'
import 'tinymce/plugins/visualblocks'
import 'tinymce/plugins/code'
import 'tinymce/plugins/fullscreen'
import 'tinymce/plugins/insertdatetime'
import 'tinymce/plugins/media'
import 'tinymce/plugins/table'
import 'tinymce/plugins/help'
import 'tinymce/plugins/wordcount'
import {editUploadFile} from "../api/common";
import {ElMessage} from "element-plus";
interface Props {
id?: string,
modelValue?: string,
height?: string | number,
width?: string | number,
disabled?: boolean,
showDel?: boolean
}
const props = withDefaults(defineProps<Props>(), {
modelValue: '',
id: 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + ''),
height: 200,
width: 'auto',
disabled: false,
showDel: false
})
const emits = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
const myValue = computed({
get() {
return props.modelValue
},
set(value) {
emits('update:modelValue', value);
},
});
const oldValue = ref<string>()
const imgAccept = ref<string>('.bmp,.jpg,.png,.tif,.gif,.pcx,.tga,.exif,.fpx,.svg,.psd,.cdr,.pcd,.dxf,.ufo,.eps,.ai,.raw,.WMF,.webp,.avif,.apng')
const example_image_upload_handler = (blobInfo: any, progress: any) => new Promise((resolve, reject) => {
let fd = new FormData();
fd.append('file', blobInfo.blob(), blobInfo.filename());
editUploadFile(fd).then((res: any) => {
if (res.code === 1) {
resolve(res.data)
} else {
resolve('')
}
})
})
const setup = (editor: any) => {
editor.ui.registry.addButton('imageUpload', {
tooltip: '圖片',
icon: 'image',
onAction: (api: any) => {
//點擊按鈕后執(zhí)行
oldValue.value = props.modelValue;
const input: any = document.getElementById(props.id);
input.click();
input.onchange = function () {
let file = input.files[0];
let fd = new FormData();
fd.append('file', file);
if (!imgAccept.value.includes(file.name.substring(file.name.indexOf('.')))) {
ElMessage.warning('請選擇圖片上傳')
input.value = '';
return
}
editUploadFile(fd).then((res: any) => {
if (res.code === 1) {
editor.insertContent("<img src='" + res.data + "' alt=''/>");
input.value = '';
} else {
editor.setContent(oldValue.value as string);
}
})
}
}
});
}
const init = reactive({
selector: `#${props.id}`,
content_style: "p {margin: 0; border:0; padding: 0;}",
content_css: '/tinymce6/skins/content/default/content.css',
language_url: '/tinymce6/langs/zh-Hans.js', // https://www.tiny.cloud/get-tiny/language-packages/
language: 'zh-Hans',
skin_url: '/tinymce6/skins/ui/oxide',
height: props.height,
promotion: false, //隱藏右上角upgrade按鈕
branding: false, //隱藏右下角由TINY驅(qū)動
menubar: false, // 是否隱藏頂部菜單
contextmenu_never_use_native: true, //防止瀏覽器上下文菜單出現(xiàn)在編輯器中
elementpath: false, //隱藏底欄的元素路徑(隱藏右下角元素顯示)
object_resizing: true,//是否允許調(diào)整圖像大小.
toolbar: 'undo redo | blocks | fontfamily forecolor |' +
'bold italic backcolor | alignleft aligncenter ' +
'alignright alignjustify | bullist numlist outdent indent | ' +
'removeformat | table | imageUpload | help',
plugins: ['advlist', 'autolink', 'lists', 'link', 'image', 'charmap', 'preview',
'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
'insertdatetime', 'media', 'table', 'help', 'wordcount'],
// paste_data_images: false, //此選項指定是否應從粘貼的內(nèi)容中刪除圖像
paste_webkit_styles: 'all', //此選項允許您指定粘貼到 WebKit 中時要保留的樣式 'none' 或者 'all'
// paste_merge_formats: true, //此選項在粘貼內(nèi)容時啟用合并格式功能对雪。這將合并相同的文本格式元素,以減少生成的 HTML 元素的數(shù)量
advlist_bullet_styles: 'default,circle,disc,square',
// advlist_number_styles: 'default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman',
link_default_target: '_blank',
link_title: false, //此選項允許您禁用對話框中的鏈接輸入字段
nonbreaking_force_tab: true, //tab鍵插入三個
images_upload_handler: example_image_upload_handler,
setup: setup
})
onMounted(() => {
tinymce.init({})
})
</script>
<style scoped>
</style>
<style>
.tox-tinymce-aux {
z-index: 3035 !important;
}
.tox .tox-toolbar__group {
padding: 0 3px 0 5px !important;
}
</style>