官网https://ckeditor.com/
此处记录一下我在使用的时候具体初始化的代码。
<template>
<div>
<textarea :id="id"></textarea>
</div>
</template>
<script>
export default {
name: 'CkEditor',
data: function () {
return {
id: parseInt(Math.random() * 10000).toString(),
ckeditor: null,
};
},
// 初始化
mounted: function () {
const self = this;
let CKEDITOR = window.CKEDITOR;
let ckeditor = window.CKEDITOR.replace(self.id, {
height: 500,
language: 'en',
allowedContent: true,
pasteFilter: null,
toolbar: [
{
name: 'code',
items: ['Source'],
},
{
name: 'basicstyles',
items: [
'Styles',
'-',
'Bold',
'Italic',
'Strike',
'Underline',
'TextColor',
'BGColor',
'Font',
'FontSize',
],
},
{
name: 'styles',
items: ['RemoveFormat'],
},
{
name: 'insert',
items: ['Table', 'SpecialChar', 'HorizontalRule'],
},
'/',
{
name: 'paragraph',
items: [
'Format',
'NumberedList',
'BulletedList',
'-',
'Indent',
'Outdent',
'-',
'JustifyLeft',
'JustifyCenter',
'JustifyRight',
'lineheight',
],
},
{
name: 'links',
items: [
'Link',
'Unlink',
'-',
'Subscribe',
'Unsubscribe',
'HtmlTemplate',
],
},
{
name: 'document',
items: ['Undo', 'Redo'],
},
],
});
// 处理图片copy、paste
ckeditor.on('paste', async (evt) => {
if (evt.data.dataTransfer.getFilesCount() > 0) {
evt.data.dataValue = '';
if (evt.data.dataTransfer.getFilesCount()) {
let file = evt.data.dataTransfer.getFile(0);
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
self.ckeditor.insertHtml(`<img src="${reader.result}"/>`);
};
reader.onerror = (error) => {
console.error(error);
};
}
}
});
// 处理tab
ckeditor.on('key', function (event) {
let keycode = event.data.keyCode;
if (keycode === 9) {
event.cancel();
ckeditor.execCommand('indent');
}
});
// 监听内容变更事件
ckeditor.on('instanceReady', () => {
self.ckeditor = ckeditor;
});
ckeditor.on('change', function () {
console.log(self.ckeditor.getData());
});
setTimeout(() => {
// 回显
this.insertDiv(
`<html>请输入文本</html>`,
);
}, 5000);
},
methods: {
// 触发
insertDiv(data) {
this.ckeditor.insertHtml(data);
},
},
};
</script>
开发的时候遇到新的问题:HTML串无法由后端直接解析得到,于是在触发insertDiv函数之前补充了一段【word文档->xml->Base64->HTML串】的处理
<template>
<div>
<h1>XML 转 Base64 转 HTML</h1>
<textarea v-model="xmlInput" placeholder="输入XML"></textarea>
<button @click="convertXmlToBase64">Convert XML to Base64</button>
<div v-if="base64Output">
<h2>Base64 为:</h2>
<textarea v-model="base64Output" readonly></textarea>
<button @click="convertBase64ToHtml">Convert Base64 to HTML</button>
</div>
<div v-if="htmlOutput">
<h2>HTML 为:</h2>
<div style="color: #fff" v-html="htmlOutput"></div>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'CkEditor',
data() {
return {
xmlInput: '',
base64Output: '',
htmlOutput: ''
};
},
methods: {
init() {
const formData = new FormData();
formData.append('filePath', 后端文件路由);
axios({
url: 后端生成word对应XML的API,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'token': 用户token,
},
data: formData,
}).then((res) => {
this.xmlInput = res.data;
this.convertXmlToBase64();
});
},
// 将 XML 转换为 Base64
convertXmlToBase64() {
if (this.xmlInput) {
const xmlText = this.xmlInput;
const base64 = btoa(encodeURIComponent(xmlText));
this.base64Output = base64;
} else {
alert('Please enter some XML first.');
}
},
// 将 Base64 转换为 HTML
convertBase64ToHtml() {
if (this.base64Output) {
const decodedXml = decodeURIComponent(atob(this.base64Output));
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(decodedXml, 'text/xml');
this.htmlOutput = xmlDoc.documentElement.outerHTML; // 直接使用 outerHTML 保留格式
} else {
alert('Please convert XML to Base64 first.');
}
}
}
};
</script>
<style>
textarea {
width: 100%;
height: 100px;
}
</style>
最后成功实现每个word文件都能转成富文本,让用户能在网页上编辑和保存文档。