mirror of
https://github.com/chansee97/nova-admin.git
synced 2025-05-21 08:19:16 +08:00
chore(rich): modify to tinymce
This commit is contained in:
parent
5d06986dbc
commit
1a9da07df3
@ -52,9 +52,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tinymce/tinymce-vue": "^5.1.0",
|
||||||
"@vueuse/core": "^10.2.0",
|
"@vueuse/core": "^10.2.0",
|
||||||
"@wangeditor/editor": "^5.1.23",
|
|
||||||
"@wangeditor/editor-for-vue": "^5.1.12",
|
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"echarts": "^5.4.2",
|
"echarts": "^5.4.2",
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<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 { MdEditor } from 'md-editor-v3' // https://imzbf.github.io/md-editor-v3/zh-CN/docs
|
||||||
import 'md-editor-v3/lib/style.css'
|
import 'md-editor-v3/lib/style.css'
|
||||||
import { useAppStore } from '@/store'
|
import { useAppStore } from '@/store'
|
||||||
@ -10,7 +12,7 @@ const theme = computed(() => {
|
|||||||
return appStore.darkMode ? 'dark' : 'light'
|
return appStore.darkMode ? 'dark' : 'light'
|
||||||
})
|
})
|
||||||
|
|
||||||
const toolbarsExclude = [
|
const toolbarsExclude: ToolbarNames[] = [
|
||||||
'mermaid',
|
'mermaid',
|
||||||
'katex',
|
'katex',
|
||||||
'github',
|
'github',
|
@ -1,9 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
112
src/components/custom/Editor/RichTextEditor/index.vue
Normal file
112
src/components/custom/Editor/RichTextEditor/index.vue
Normal 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 media分别对应三个类型文件的上传:link插件,image和axupimgs插件,media插件。想屏蔽某个插件的上传就去掉对应的参数
|
||||||
|
// 文件上传处理函数
|
||||||
|
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>
|
@ -1,4 +0,0 @@
|
|||||||
import MdEditor from './MdEditor.vue'
|
|
||||||
import RichEditor from './RichEditor.vue'
|
|
||||||
|
|
||||||
export { MdEditor, RichEditor }
|
|
@ -4,7 +4,7 @@ const text = ref('# Hello Editor 
|
||||||
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>')
|
|
||||||
|
|
||||||
// 模拟 ajax 异步获取内容
|
// 模拟 ajax 异步获取内容
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
valueHtml.value = '<p>模拟 Ajax 异步设置内容</p>'
|
text.value = '<p>模拟 Ajax 异步设置内容</p>'
|
||||||
}, 1500)
|
}, 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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-card>
|
<n-card>
|
||||||
<div style="border: 1px solid #ccc">
|
<RichTextEditor v-model="text" />
|
||||||
<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>
|
|
||||||
</n-card>
|
</n-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user