chore(rich): modify to tinymce

This commit is contained in:
Coffee-crocodile 2023-06-21 18:07:28 +08:00
parent 5d06986dbc
commit 1a9da07df3
7 changed files with 120 additions and 55 deletions

View File

@ -52,9 +52,8 @@
}
},
"dependencies": {
"@tinymce/tinymce-vue": "^5.1.0",
"@vueuse/core": "^10.2.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
"axios": "^1.4.0",
"crypto-js": "^4.1.1",
"echarts": "^5.4.2",

View File

@ -1,4 +1,6 @@
<script setup lang="ts">
import type { ToolbarNames } from 'md-editor-v3'
import { MdEditor } from 'md-editor-v3' // https://imzbf.github.io/md-editor-v3/zh-CN/docs
import 'md-editor-v3/lib/style.css'
import { useAppStore } from '@/store'
@ -10,7 +12,7 @@ const theme = computed(() => {
return appStore.darkMode ? 'dark' : 'light'
})
const toolbarsExclude = [
const toolbarsExclude: ToolbarNames[] = [
'mermaid',
'katex',
'github',

View File

@ -1,9 +0,0 @@
<script setup lang="ts">
</script>
<template>
<div />
</template>
<style scoped></style>

View File

@ -0,0 +1,112 @@
<script setup lang="ts">
import Editor from '@tinymce/tinymce-vue'
const modelValue = defineModel()
function imagesUploadHandler(blobInfo, _progress) {
return new Promise((resolve, reject) => {
const formData = new FormData()
formData.append('file', blobInfo.blob())
fetch('www.example.com/upload', {
method: 'POST',
body: formData,
})
.then((response) => {
if (!response.ok)
throw new Error('上传失败')
//
resolve(data)
})
.catch((error) => {
//
reject(error)
})
})
}
function filesUploadHandler(callback, value, meta) {
// 使http://tinymce.ax-z.cn/general/upload-images.php
// meta.filetype //file image media
let filetype // ,
if (meta.filetype === 'image')
filetype = '.jpg, .jpeg, .png, .gif, .ico, .svg'
else if (meta.filetype === 'media')
filetype = '.mp3, .mp4, .avi, .mov'
else
filetype = '.pdf, .txt, .zip, .rar, .7z, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .mp3, .mp4, .jpg, .jpeg, .png, .gif, .ico, .svg'
const inputElem = document.createElement('input') //
inputElem.setAttribute('type', 'file')
inputElem.setAttribute('accept', filetype)
inputElem.click()
inputElem.onchange = () => {
const file = inputElem.files[0] //
// base64,https://www.tiny.cloud/docs/configure/file-image-upload/#file_picker_callback
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = function () {
// Note: Now we need to register the blob in TinyMCEs image blob
// registry. In the next release this part hopefully won't be
// necessary, as we are looking to handle it internally.
const id = `blobid${new Date().getTime()}`
const blobCache = tinymce.activeEditor.editorUpload.blobCache
const base64 = reader.result.split(',')[1]
const blobInfo = blobCache.create(id, file, base64)
blobCache.add(blobInfo)
// call the callback and populate the Title field with the file name
callback(blobInfo.blobUri(), { title: file.name })
}
}
}
const initConfig = {
language: 'zh_CN', //
min_height: 700,
content_css: 'dark',
placeholder: '请输入内容', // textarea
branding: false,
font_formats:
'微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;', //
plugins:
'print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount textpattern autosave emoticons', // axupimgs indent2em
toolbar: [
'fullscreen undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough anchor | alignleft aligncenter alignright alignjustify outdent indent | bullist numlist | blockquote subscript superscript removeformat ',
'styleselect formatselect fontselect fontsizeselect | table image axupimgs media link emoticons charmap hr pagebreak insertdatetime selectall visualblocks | code preview | indent2em lineheight formatpainter',
],
paste_data_images: true, //
//
images_upload_handler: imagesUploadHandler,
file_picker_types: 'file image media', // file image medialinkimageaxupimgsmedia
//
file_picker_callback: filesUploadHandler,
}
</script>
<template>
<div class="tinymce-boxz">
<Editor
v-model="modelValue"
api-key="no-api"
:init="initConfig"
/>
</div>
</template>
<style>
.tinymce-boxz > textarea {
display: none;
}
/* 隐藏apikey没有绑定这个域名的提示 */
.tox-notifications-container .tox-notification--warning {
display: none !important;
}
.tox.tox-tinymce {
max-width: 100%;
}
</style>

View File

@ -1,4 +0,0 @@
import MdEditor from './MdEditor.vue'
import RichEditor from './RichEditor.vue'
export { MdEditor, RichEditor }

View File

@ -4,7 +4,7 @@ const text = ref('# Hello Editor ![图片描述](https://via.placeholder.com/350
<template>
<n-card>
<MdEditor v-model="text" />
<MarkDownEditor v-model="text" />
</n-card>
</template>

View File

@ -1,51 +1,16 @@
<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css' // css
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
// https://www.wangeditor.com/v5/getting-started.html
// shallowRef
const editorRef = shallowRef()
//
const mode = 'default' // 'simple'
// HTML
const valueHtml = ref('<p>hello</p>')
const text = ref('')
// ajax
onMounted(() => {
setTimeout(() => {
valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>'
text.value = '<p>模拟 Ajax 异步设置内容</p>'
}, 1500)
})
const toolbarConfig = {}
const editorConfig = { placeholder: '请输入内容...' }
//
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor === null)
return
editor.destroy()
})
function handleCreated(editor: string) {
editorRef.value = editor // editor
}
</script>
<template>
<n-card>
<div style="border: 1px solid #ccc">
<Toolbar style="border-bottom: 1px solid #ccc" :editor="editorRef" :default-config="toolbarConfig" :mode="mode" />
<Editor
v-model="valueHtml"
style="height: 500px; overflow-y: hidden"
:default-config="editorConfig"
:mode="mode"
@on-created="handleCreated"
/>
</div>
<RichTextEditor v-model="text" />
</n-card>
</template>