vue3笔记(41-3)AIGC-富文本编辑器-WangEditor

背景:大模型生成文章内容,需要使用富文本编辑器进行内容的编辑。其中敏感词汇需要标注,最后可以生成word、pdf等格式的文档。

调研

目前市面上有好多富文本编辑器,我们的需求是开源免费、不要二次开发(人力&时间有限)。本篇记录wangEditor实验。

Demo 过程

这里使用了 wangEditor 5 作为富文本编辑器。

1
npm install @wangeditor/editor-for-vue@next --save

使用包中自带的组件,渲染如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div style="border: 1px solid #ccc; width: 100%; margin: 0 auto">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editorRef"
:defaultConfig="toolbarConfig"
mode="default"
/>
<Editor
style="height: 500px; overflow-y: hidden"
v-model="valueHtml"
:defaultConfig="editorConfig"
mode="default"
@onCreated="handleCreated"
@customPaste="customPaste"
/>
</div>
<el-button style="margin: 0 auto" @click="getEditorHTML">提交</el-button>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import '@wangeditor/editor/dist/css/style.css'
import { onBeforeUnmount, ref, shallowRef } from 'vue'
// 导入富文本编辑器的组件
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'

// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef()

// 内容 HTML
const valueHtml = ref('')
const toolbarConfig = {}
const editorConfig = ref({ placeholder: '请输入内容...', MENU_CONF: {} })

// 自定义图片上传
editorConfig.value.MENU_CONF['uploadImage'] = {
async customUpload(file, insertFn) {
console.log('上传图片', file)
// 将上传的file图片转换为base64
const base64 = URL.createObjectURL(file)
// 这里的file为上传的图片对象,insertFn传入
insertFn(base64, 'img')
}
}

// 自定义视频上传
editorConfig.value.MENU_CONF['uploadVideo'] = {
async customUpload(file, insertFn) {
console.log('上传视频', file)
}
}

// 富文本编辑器生成后触发
const handleCreated = (editor) => {
editorRef.value = editor // 记录 editor 实例,重要!
console.log(editorConfig.value.MENU_CONF, 'editorConfig.value')
}

// 监听富文本编辑器粘贴行为
const customPaste = (editor, event, callback) => {
// 获取粘贴的纯文本
const text = event.clipboardData.getData('text/plain')
if (text) {
editor.insertText(text)
event.preventDefault()
callback(false)
}
}

// 获取富文本html内容
const getEditorHTML = () => {
console.log(editorRef.value.getHtml())
}

onMounted(() => {
setTimeout(() => {
valueHtml.value = '<p>模拟 Ajax 异步设置内容 HTML</p>'
}, 1500)
})

// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
const editor = editorRef.value
if (editor == null) return
editor.destroy()
})

隐藏菜单栏

官方有toolbar.getConfig().toolbarKeys这个方法,但是在 vue3 中没有成功,不确定应该在什么时候调用。
实验发现,在菜单栏中通过网页元素查看data-menu-key确定菜单栏的名字,然后在toolbarConfig中设置excludeKeys属性,将不需要的菜单栏隐藏。

1
2
3
const toolbarConfig = {
excludeKeys: ['emotion']
}

自动保存

监听 Ctr + S

1
2
3
4
5
6
7
8
9
10
11
 const keyDown = (event) => {
let currentKey = event.keyCode || event.which
if (currentKey === 83 && (event.ctrlKey || event.metaKey)) {
event.preventDefault()
console.log('ctrl S')
}
}

onMounted(() => {
document.addEventListener('keydown', keyDown)
})

生成文档并下载

word 文档

1
npm install html-docx-js-typescript --save
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { asBlob } from 'html-docx-js-typescript';//将html转为word

const exportDoc = async () => {
const editor = editorRef.value
// 将富文本内容拼接为一个完整的html
const html = editor.getHtml()
const value = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
${html}
</body>
</html>`
const data = await asBlob(value, { orientation: 'portrait' }) as Blob
const a = document.createElement('a')
a.href = window.URL.createObjectURL(data)
a.setAttribute('download', 'document.docx')
a.click()
a.remove()
}

结果如下:
word文档效果

结论

可实现全屏编辑;
可实现鼠标键盘复制粘贴功能;
可实现选中文字调出工具栏;
可实现代码高亮(可选语言,但是浮动框被工具栏遮挡住部分);
可实现本地上传图片,目前为 base64 保存和传输;
可实现初始化内容;
可实现隐藏菜单栏;
可实现键盘事件 ctrl S 触发自动报错;
可实现保存为 word 并下载,会保留基本格式(字体可能不行,需要安装字体?),会自动分页;
尝试生成pdf,失败(要么打开不了,要么就是纯html,没有变成有格式的文字);

附录
wangEditor 5
自动保存
Vue3+TS实现将html或富文本编辑器转为Word并下载
14款web前端常用的富文本编辑器插件
UEditor 是百度的项目,已于2023年6月暂停维护;