书接上回,我们实现了富文本编辑器的工具栏图片上传按钮选择图片后,可以将图片上传至服务器,这一篇,来看看当我们复制了一张图片到剪贴板,粘贴到编辑器文本编辑区域时,如何同步上传至服务器呢?
功能实现
我们的实现步骤是:
当我们点击 Ctrl + V 的时候,FluentEditor 默认粘贴(插入 base64 图片),此处触发我们自己的粘贴处理方法 handlePaste,此时上传图片,调用FluentEditor 的 .insertEmbed 方法插入图片地址。这里直接上代码:
javascript
<template>
<div class="editor-container">
<div ref="editorRef" class="editor-inside"></div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import '@opentiny/fluent-editor/style.css'
import FluentEditor from '@opentiny/fluent-editor'
import axios from 'axios'
import { uploadFile } from '@/model/editor.js' // 这里使用自己的上传接口即可
const editorRef = ref(null)
let editorInstance = null
const TOOLBAR_CONFIG = [
[{ header: [] }],
['bold', 'italic', 'underline', 'link'],
[{ list: 'ordered' }, { list: 'bullet' }],
['clean'],
['image']
]
const selectImage = () => {
const input = document.createElement('input')
input.type = 'file'
input.accept = 'image/*'
input.click()
input.onchange = async () => {
const file = input.files[0]
if (!file) return
try {
const url = await uploadImage(file)
const range = editorInstance.getSelection()
editorInstance.insertEmbed(range.index, 'image', url)
} catch (err) {
console.error('上传失败', err)
}
}
}
const uploadImage = async (file) => {
const ext = file.name.split('.').pop()
const res = await uploadFile({ ext })
const resData = res.data
const uploadUrl = resData.upload_url
const fileUrl = resData.public_url
await axios.put(uploadUrl, file, {
headers: {
'Content-Type': file.type
}
})
return fileUrl
}
const handlePaste = async (e) => {
const items = e.clipboardData?.items
if (!items) return
for (let i = 0; i < items.length; i++) {
const item = items[i]
if (item.type.indexOf('image') !== -1) {
e.preventDefault()
e.stopPropagation()
const file = item.getAsFile()
try {
const url = await uploadImage(file)
const range = editorInstance.getSelection(true)
editorInstance.insertEmbed(range.index, 'image', url)
} catch (err) {
console.error('粘贴上传失败', err)
}
break
}
}
}
onMounted(() => {
if (!editorRef.value) return
editorInstance = new FluentEditor(editorRef.value, {
theme: 'snow',
modules: {
toolbar: {
container: TOOLBAR_CONFIG,
handlers: {
image: selectImage
}
}
}
})
editorRef.value.addEventListener('paste', handlePaste, true)
})
</script>
<style scoped>
.editor-container {
width: 50%;
display: flex;
justify-content: center;
padding-top: 20px;
}
.editor-inside {
height: 350px;
}
.editor-inside :deep(.ql-container) {
height: 350px;
}
.editor-inside :deep(.ql-editor) {
height: 310px;
}
</style>
注意:我们在监听 paste 的时候,第三个入参传了 true,是为了阻止编辑器默认的图片粘贴行为,如果不写,那么我们在粘贴图片的时候,会粘贴进去两张图片。
下一篇,我们看看将图片拖拽到编辑器中如何渲染和上传。