EyouCMS从百度UEditor更换为Markdown MrEditor编辑器教程
发表时间:2026-05-15 22:35:07
文章作者:小编
浏览次数:
一、为什么要替换UEditor
EyouCMS默认使用百度UEditor作为富文本编辑器。UEditor功能强大,但存在以下问题:
- 停止维护:百度UEditor已多年未更新,存在安全隐患
- 体积庞大:UEditor完整包超过5MB,影响后台加载速度
- 排版困难:富文本编辑容易产生冗余HTML标签,排版不一致
- 代码不友好:插入代码块体验差,无语法高亮
MrEditor 是一款基于 CodeMirror 6 的现代 Markdown 编辑器,具备以下优势:
- 左右分栏实时预览,所见即所得
- 原生 Markdown 语法,排版干净整洁
- 代码块语法高亮,支持多种编程语言
- 支持数学公式、Mermaid 流程图
- 轻量级,加载速度快
- 粘贴图片自动上传
二、准备工作
2.1 所需文件
需要准备以下插件文件:
文件
用途
存放路径
mreditor.js
MrEditor 编辑器核心
/public/plugins/mr-editor/
mreditor.css
编辑器样式
/public/plugins/mr-editor/
global.css
全局样式
/public/plugins/mr-editor/
marked.min.js
Markdown→HTML 解析器
/public/plugins/mr-marked/
marked.css
渲染样式
/public/plugins/mr-marked/
turndown.min.js
HTML→Markdown 转换器
/public/plugins/turndown/
mreditor_helper.js
桥接层(核心)
/public/static/admin/js/
2.2 MrEditor 来源
MrEditor 来自 MrDoc(觅思文档)项目,是一个基于 Svelte + CodeMirror 6 构建的 Markdown 编辑器。
marked.js 用于将 Markdown 转为 HTML(保存到数据库),turndown.js 用于将 HTML 转回 Markdown(从数据库加载时)。
三、核心实现:桥接层 mreditor_helper.js
这是整个替换方案的核心文件。EyouCMS 的内容管理流程是:
数据库存储 HTML → 编辑器加载 HTML → 编辑器输出 HTML → 保存到数据库
而 MrEditor 操作的是 Markdown,所以需要一个桥接层来做格式转换:
加载时:HTML(数据库) → turndown → Markdown(编辑器)
保存时:Markdown(编辑器) → marked → HTML(数据库)
3.1 桥接层核心结构
var MrEditorHelper = {
_instances: {}, // MrEditor 实例
_textareas: {}, // 原始 textarea 引用
_wrappers: {}, // 编辑器容器 DOM
// 创建编辑器实例
create: function(id, options) { ... },
// 获取 HTML 内容(MD→HTML)
getContent: function(id) { ... },
// 设置 HTML 内容(HTML→MD)
setContent: function(id, html) { ... },
// 在光标处插入内容
insertHtml: function(id, html) { ... },
// 同步内容到原始 textarea
sync: function(id) { ... },
// HTML→MD 转换
_htmlToMd: function(html) { ... },
// MD→HTML 转换
_mdToHtml: function(md) { ... },
// 清理渲染器产生的装饰元素
_cleanHtml: function(html) { ... },
// 粘贴图片上传
_bindPasteUpload: function(id, wrapper, uploadUrl) { ... }
};
3.2 API 兼容设计
桥接层提供了与 UEditor / Vditor 兼容的 API 接口:
方法
说明
MrEditorHelper.create(id, opts)
替代 UE.getEditor(id)
MrEditorHelper.getContent(id)
替代 UE.getEditor(id).getContent()
MrEditorHelper.setContent(id, html)
替代 UE.getEditor(id).setContent(html)
MrEditorHelper.insertHtml(id, html)
替代 UE.getEditor(id).execCommand('insertHtml', html)
MrEditorHelper.sync(id)
表单提交前同步内容
3.3 HTML 清洗机制
marked.js 渲染 Markdown 时会给代码块添加工具栏(复制按钮、语言标签等装饰元素)。如果这些装饰元素被保存到数据库,下次加载时会变成多余的文本。
桥接层内置了 _cleanHtml() 方法,在加载和保存时自动清理:
- 移除
.markdown-code-toolbar(代码块工具栏) - 解包
.markdown-code容器,只保留<pre><code> - 移除标题中的重复锚点链接
- 清理工具栏文本残留(如孤立的"复制"段落)
四、模板文件修改
4.1 引入资源文件
在后台模板文件(如 edit.htm、add.htm)的头部,替换原有 UEditor 引用:
<!-- 移除 UEditor 引用 -->
<!-- {load href="__PUBLIC__/plugins/ueditor/...} -->
<!-- 添加 MrEditor 引用 -->
{load href="__PUBLIC__/plugins/mr-marked/marked.min.js" /}
{load href="__PUBLIC__/plugins/turndown/turndown.min.js" /}
{load href="__PUBLIC__/plugins/mr-editor/mreditor.js" /}
{load href="__PUBLIC__/plugins/mr-editor/global.css" /}
{load href="__PUBLIC__/plugins/mr-marked/marked.css" /}
{load href="__PUBLIC__/plugins/mr-editor/mreditor.css" /}
{load href="__STATIC__/admin/js/mreditor_helper.js" /}
4.2 初始化编辑器
将原有 UEditor 初始化代码替换为:
MrEditorHelper.create('addonFieldExt_content', {
serverUrl: "{:url('Ueditor/index',array('savepath'=>'allimg'))}",
height: 450,
toolbars: mreditor_toolbars
});
4.3 需要修改的模板文件
EyouCMS 中涉及编辑器的模板文件较多,需要逐一替换:
模板文件
说明
article/edit.htm
文章编辑页
article/add.htm
文章新增页
article/free_content.htm
自定义内容弹窗
archives/get_field_addonextitem.htm
扩展字段编辑器
field/modelfield.htm
模型字段设置
field/addonitem.htm
附加字段项
other/edit.htm、other/add.htm
其他内容编辑
五、关键问题与修复
5.1 按钮触发表单提交
问题:MrEditor 工具栏按钮是 <button> 标签,HTML 规范中 <form> 内的 <button> 默认为 type="submit",点击会触发表单提交。
解决:在桥接层中使用 MutationObserver 监听所有 button 元素,自动设置 type="button":
function fixButtonType(btn) {
if (!btn.getAttribute('type') || btn.getAttribute('type') === 'submit') {
btn.setAttribute('type', 'button');
}
}
// 初始修复 + MutationObserver 监听动态按钮
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(m) {
m.addedNodes.forEach(function(node) {
if (node.nodeType !== 1) return;
if (node.tagName === 'BUTTON') fixButtonType(node);
var inner = node.querySelectorAll ? node.querySelectorAll('button') : [];
for (var n = 0; n < inner.length; n++) fixButtonType(inner[n]);
});
});
});
observer.observe(wrapper, { childList: true, subtree: true });
5.2 下拉菜单 tooltip 显示 undefined
问题:MrEditor 下拉类按钮(字体、引用提示块、公式等)没有设置 data-tippy-content 属性,鼠标悬停显示 "undefined"。
解决:延迟等待 tippy 实例挂载完成后,手动设置中文名称:
var dropdownTitles = {
'font': '字体', 'quote-tips': '引用提示块',
'formula': '公式', 'graph': '图表', 'mermaid': 'Mermaid 图表'
};
function fixDropdownTippy(retries) {
var dropdowns = wrapper.querySelectorAll('.toolbar-item-tippy-dropdown');
// ... 延迟重试修复
}
setTimeout(function() { fixDropdownTippy(10); }, 300);
5.3 PC端/手机端切换不同步
问题:EyouCMS 的 contentSwitch() 通过 jQuery show/hide 切换 PC端/手机端 textarea,但 MrEditor wrapper 是 textarea 的兄弟节点,不受影响。
解决:拦截 contentSwitch() 函数,同步操作 MrEditor wrapper 的显示/隐藏。
5.4 粘贴图片上传
解决:在 .cm-content 元素上监听 paste 事件,检测剪贴板中的图片文件,通过 FormData + AJAX 上传到服务器,上传成功后插入 Markdown 图片语法:
editorEl.addEventListener('paste', function(ev) {
// 检测图片 → FormData 上传 → 插入 
}, true);
六、前端显示适配
数据库中存储的是 HTML,前端模板直接输出即可,无需额外处理。但需要为代码块添加 CSS 样式:
/* 文章内容区代码块样式 */
.case_info .text pre {
background: #f6f6f6;
padding: 10px;
overflow: auto;
border-radius: 3px;
margin: 16px 0;
}
.case_info .text pre code {
background: transparent;
color: #24292e;
font-size: 0.85em;
line-height: 1.6;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}
/* 正文排版 */
.case_info .text {
font-size: 16px;
line-height: 1.75;
}
.case_info .text p {
margin: 12px 0;
}
.case_info .text img {
display: block;
margin: 20px 0;
max-width: 100%;
height: auto;
}
七、效果展示
替换完成后,后台编辑器界面如下:

左侧为 Markdown 源码编辑区,右侧为实时预览区。支持工具栏快捷操作、代码高亮、图片粘贴上传等功能。

八、总结
对比项
UEditor
MrEditor
维护状态
已停更
活跃维护
文件体积
5MB+
< 1MB
编辑模式
富文本 WYSIWYG
Markdown 分栏预览
代码块
无语法高亮
CodeMirror 6 高亮
排版一致性
易产生冗余标签
Markdown 语法干净
图片上传
内置复杂上传组件
粘贴即上传
扩展性
插件体系复杂
轻量可定制
通过桥接层设计,实现了零侵入替换——不需要修改 EyouCMS 核心代码,只需替换模板文件中的编辑器引用,所有内容管理流程(新增、编辑、保存、前端展示)完全兼容。










