1. Install
npm install @tinymce/tinymce-vue -S
2. Encapsulate and build a component
<template>
<div>
<Editor
api-key="xxxxx"
tinymceScriptSrc="/tinymce/tinymce.min.js"
:init="{
language: 'zh_CN',
height: 500,
paste_data_images: true, // 允许粘贴图像
paste_webkit_styles: 'all',
automatic_uploads: true,
convert_urls: false,
image_caption: true,
content_style: `
*{
margin:0;
padding:0;
}
body{
font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Helvetica,
Segoe UI, Arial, Roboto, PingFang SC, miui, Hiragino Sans GB,
Microsoft Yahei, sans-serif !important;
}
h1,h2,h3,h4,h5,h6,h7{
font-size: 18px;
}
p,font{
font-size: 16px;
font-weight: 400;
color: #262626;
line-height: 24px;
text-align: justify;
word-break: break-all;
letter-spacing: 1.5px;
}
p{
text-indent:0;
margin:0;
}
strong span{
display: block;
}
div img,p img,img,span img{
width:50% !important;
height:auto;
text-align:center;
border-radius: 4px;
display: block;
margin: 15px auto 0 auto;
}
figcaption{
text-align:center !important;
margin: 20px 0 !important;
}
figure{
margin: 0 auto !important;
}
`,
toolbar: [
'image media video bold fontsize forecolor backcolor italic underline strikethrough styleselect fontsizeselect alignleft aligncenter alignright alignjustify outdent indent lineheight cut copy outdent indent undo redo blockquote table preview fullscreen',
],
menubar: false,
branding: false,
fontsize_formats: '11px 12px 14px 16px 17px 18px 24px 36px 48px',
lineheight_formats: '10px 20px 30px 40px 50px 60px',
imagetools_toolbar: 'imageoptions',
file_picker_callback: file_picker_callback,
paste_preprocess: paste_preprocess,
init_instance_callback: init_instance_callback,
images_upload_handler: example_image_upload_handle,
urlconverter_callback: urlconverter_callback,
}"
v-model="content"
:plugins="['image', 'fullscreen', 'media', 'preview', 'paste']"
@change="handleChange"
></Editor>
</div>
</template>
<script lang="ts" setup>
import {
ref, watch } from "vue";
import Editor from "@tinymce/tinymce-vue";
import {
uploadFiles } from "@/utils/funtional";
import axios from "axios";
import {
message } from "ant-design-vue";
let props = defineProps<{
readOnly?: boolean;
value: string;
}>();
let emits = defineEmits(["handleChange"]);
let content = ref<string>();
let editorRef: any;
watch(
() => props.value,
(val) => {
content.value = val;
},
{
deep: true,
immediate: true,
}
);
// 图片直接粘贴
const paste_preprocess = (_: any, args: Record<string, any>) => {
if (args.content.indexOf("xiumi") !== -1) {
return args.content;
}
const styleTag = /\s+style="[^"]*"/gi;
args.content = args.content
.replace(styleTag, () => {
return "";
})
.replace(/( )|(<br>)|(<br\/>)/gi, () => {
return "";
});
};
// 文件上传
const file_picker_callback = (
callback: (key: string) => void,
value: string,
meta: Record<string, string>
) => {
if (meta.filetype === "image") {
if (!value) return;
axios({
url: value,
method: "get",
responseType: "arraybuffer",
}).then((res) => {
let code = btoa(
new Uint8Array(res.data).reduce(
(data, byte) => data + String.fromCharCode(byte),
""
)
);
let a = document.createElement("a");
a.setAttribute("href", "data:image/png;base64," + code);
a.download = "image" + new Date().getTime();
a.click();
a.remove();
});
}
if (meta.filetype === "media") {
let fileInput = document.createElement("input");
fileInput.setAttribute("type", "file");
fileInput.setAttribute("accept", ".mp4");
fileInput.click();
fileInput.addEventListener("change", async (e: any) => {
let url = await uploadFiles(e.target.files[0]);
callback(url);
fileInput.remove();
});
}
};
// 图片上传
const example_image_upload_handle = async (
blobInfo: Record<string, any>,
success: (url: string) => void,
failFun: (mes: string) => void
) => {
let maxSize = blobInfo.blob().size / 1024 / 1024;
if (maxSize > 10) {
return failFun("请上传10M以内的图片");
}
let url = await uploadFiles(blobInfo.blob());
success(url);
};
const urlconverter_callback = (url: string) => {
return url;
};
const init_instance_callback = (ref: any) => {
editorRef = ref;
if (props.readOnly) {
editorRef.setMode("readonly");
}
};
const handleChange = () => {
emits("handleChange", content.value);
};
</script>
3. Page introduction and use
<editor :value="value"/>
Finish
Note : When using it, the following error will occasionally appear . The js of the rich text plug-in cannot be found on the server, resulting in the rich
text not being loaded. Put it inside (if Chinese is required)
Then the page imports
tinymceScriptSrc="/tinymce/tinymce.min.js"
In this way, the loading of rich text will be faster, and the js file will not be found.