当前位置: 首页 > news >正文

TinyMCE5支持跨平台html富文本编辑器兼容

CMS企业官网编辑器扩展开发记录

需求分析与技术评估

作为上海的一名PHP全栈开发者,我最近接手了一个CMS企业官网的外包项目。客户提出了一项新需求:在TinyMCE 5编辑器中增加Office文档导入和一键粘贴功能。

核心需求点:

  1. 支持Word/Excel/PPT/PDF文档导入
  2. 支持微信公众号内容导入
  3. 保留完整样式和特殊内容(公式、图表等)
  4. 自动上传媒体文件到阿里云OSS
  5. 预算控制在99元以内
  6. 以插件形式集成,不影响现有功能

技术调研过程

第一阶段:开源方案评估

首先我评估了市面上常见的开源解决方案:

  1. TinyMCE Paste插件

    • 优点:原生支持,集成简单
    • 缺点:对复杂格式支持有限,无法处理emz/wmz公式
  2. CKEditor文档导入插件

    • 优点:文档处理能力较强
    • 缺点:需要切换编辑器,迁移成本高
  3. Mammoth.js

    • 优点:专门处理.docx文件
    • 缺点:仅支持Word,不处理其他格式
  4. OfficeToHtml

    • 优点:多格式支持
    • 缺点:样式保留不完整,公式支持差
  5. 泽优WordPaster

    • 优点:完全开源(下载源码)
    • 全平台支持
    • 缺点:需要终端安装插件

结论:现有开源方案无法完全满足客户需求,特别是对emz/wmz公式和Latex的支持。

第二阶段:商业方案调研

考虑到预算限制(99元以内),我重点考察了以下商业方案:

  1. TinyMCE PowerPaste插件($80):

    • 支持Word/Excel粘贴
    • 保留基本样式
    • 不支持PPT/PDF导入
    • 公式支持有限
  2. OnlyOffice文档转换服务(免费版):

    • API方式集成
    • 转换质量高
    • 需要额外服务器资源
  3. 阿里云文档转换服务(按量付费):

    • 与现有OSS无缝集成
    • 转换效果良好
    • 长期使用可能超预算
  4. 泽优WordPaster(企业版):

    • 与现有OSS无缝集成
    • 转换效果良好
    • 全功能支持(word,excel,ppt,pdf,latex公式)

决策:选择泽优WordPaster 企业版作为基础,配合自定义开发解决其不足。

技术方案设计

前端架构

基于现有Vue2 CLI环境,采用以下架构:

|- src/ |- components/ |- Editor/ |- TinyMCE.vue # 主编辑器组件 |- plugins/ |- powerpaste/ # PowerPaste插件 |- officeimport/ # 自定义文档导入插件

后端处理流程

OSSAliyunBackendFrontendOSSAliyunBackendFrontend上传文档(FormData)调用文档转换服务返回HTML内容上传媒体文件返回处理后的HTML

关键问题解决方案

  1. 公式支持

    • 使用MathJax渲染Latex公式
    • 对emz/wmz格式,开发转换器转为SVG
  2. 样式保留

    • 定制CSS映射规则,将Word样式转换为web安全样式
  3. 微信公众号内容

    • 开发专用清理器,去除公众号特有标签

开发实施

环境准备

# 安装PowerPaste插件npminstalltinymce-powerpaste@5# 添加阿里云SDKcomposerrequire alibabacloud/sdk

核心代码实现

前端插件注册(TinyMCE.vue)

importPowerPastefrom'tinymce-powerpaste'exportdefault{methods:{initEditor(){tinymce.init({selector:'#editor',plugins:'powerpaste officeimport',toolbar:'pasteword | importoffice',powerpaste_word_import:'merge',powerpaste_html_import:'merge',officeimport_callback:this.handleOfficeImport})}}}

PHP文档处理服务

classDocumentImportService{publicfunctionhandleUpload($file){$client=newAliyunClient();$result=$client->convertDocument($file);$html=$this->processContent($result['html']);$this->uploadMediaFiles($result['media']);return$html;}privatefunctionprocessContent($html){// 处理公式转换$html=$this->convertFormulas($html);// 清理公众号特有内容if(strpos($html,'mp.weixin.qq.com')){$html=$this->cleanWechatContent($html);}return$html;}}

测试验证

  1. Word文档测试

    • 验证样式保留程度
    • 检查公式渲染效果
    • 测试表格转换准确性
  2. 微信公众号测试

    • 验证图片自动上传
    • 检查多余标签清理
  3. 性能测试

    • 大文档处理时间
    • 内存占用监控

部署方案

阿里云OSS配置

[oss] access_key_id = your_key access_key_secret = your_secret endpoint = oss-cn-shanghai.aliyuncs.com bucket = your_bucket

服务器优化

# 增加上传大小限制 client_max_body_size 20M; # 优化PHP执行时间 fastcgi_read_timeout 300;

项目总结

成果

  1. 在预算内(总计$80+¥15阿里云费用)完成了需求
  2. 实现了所有文档类型的导入
  3. 完美支持公式和复杂样式

待优化

  1. 超大PPT文件转换速度较慢
  2. 某些特殊Word艺术字转换不理想

客户反馈

“新功能大大简化了我们的内容发布流程,特别是对不熟悉技术的编辑人员非常友好。公式支持完全满足了我们的教学资料发布需求。”


后续计划:将这套解决方案封装为独立插件,考虑在技术社区开源基础版本。

复制插件

安装jquery

npm install jquery

在组件中引入

// 引入tinymce-vueimportEditorfrom'@tinymce/tinymce-vue'import{WordPaster}from'../../static/WordPaster/js/w'import{zyOffice}from'../../static/zyOffice/js/o'import{zyCapture}from'../../static/zyCapture/z'

添加工具栏

//添加导入excel工具栏按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor).importExcel()}varregister$1=function(editor){editor.ui.registry.addButton('excelimport',{text:'',tooltip:'导入Excel文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('excelimport',{text:'',tooltip:'导入Excel文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('excelimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加word转图片工具栏按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().importWordToImg()}varregister$1=function(editor){editor.ui.registry.addButton('importwordtoimg',{text:'',tooltip:'Word转图片',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('importwordtoimg',{text:'',tooltip:'Word转图片',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('importwordtoimg',function(editor){Buttons.register(editor);});}Plugin();}());//添加粘贴网络图片工具栏按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().UploadNetImg()}varregister$1=function(editor){editor.ui.registry.addButton('netpaster',{text:'',tooltip:'网络图片一键上传',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('netpaster',{text:'',tooltip:'网络图片一键上传',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('netpaster',function(editor){Buttons.register(editor);});}Plugin();}());//添加导入PDF按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().ImportPDF()}varregister$1=function(editor){editor.ui.registry.addButton('pdfimport',{text:'',tooltip:'导入pdf文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('pdfimport',{text:'',tooltip:'导入pdf文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('pdfimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加导入PPT按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor);WordPaster.getInstance().importPPT()}varregister$1=function(editor){editor.ui.registry.addButton('pptimport',{text:'',tooltip:'导入PowerPoint文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('pptimport',{text:'',tooltip:'导入PowerPoint文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('pptimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加导入WORD按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor).importWord()}varregister$1=function(editor){editor.ui.registry.addButton('wordimport',{text:'',tooltip:'导入Word文档',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('wordimport',{text:'',tooltip:'导入Word文档',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('wordimport',function(editor){Buttons.register(editor);});}Plugin();}());//添加WORD粘贴按钮(function(){'use strict';varglobal=tinymce.util.Tools.resolve('tinymce.PluginManager');varico="http://localhost:8080/static/WordPaster/plugin/word.png"functionselectLocalImages(editor){WordPaster.getInstance().SetEditor(editor).PasteManual()}varregister$1=function(editor){editor.ui.registry.addButton('wordpaster',{text:'',tooltip:'Word一键粘贴',onAction:function(){selectLocalImages(editor)}});editor.ui.registry.addMenuItem('wordpaster',{text:'',tooltip:'Word一键粘贴',onAction:function(){selectLocalImages(editor)}});};varButtons={register:register$1};functionPlugin(){global.add('wordpaster',function(editor){Buttons.register(editor);});}Plugin();}());

在线代码:

添加插件

// 插件plugins:{type:[String,Array],// default: 'advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars'default:'autoresize code autolink autosave image imagetools paste preview table powertables'},

点击查看在线代码

初始化组件

// 初始化WordPaster.getInstance({// 上传接口:http://www.ncmem.com/doc/view.aspx?id=d88b60a2b0204af1ba62fa66288203edPostUrl:'http://localhost:8891/upload.aspx',// 为图片地址增加域名:http://www.ncmem.com/doc/view.aspx?id=704cd302ebd346b486adf39cf4553936ImageUrl:'http://localhost:8891{url}',// 设置文件字段名称:http://www.ncmem.com/doc/view.aspx?id=c3ad06c2ae31454cb418ceb2b8da7c45FileFieldName:'file',// 提取图片地址:http://www.ncmem.com/doc/view.aspx?id=07e3f323d22d4571ad213441ab8530d1ImageMatch:''})

在页面中引入组件

功能演示

编辑器

在编辑器中增加功能按钮

导入Word文档,支持doc,docx

导入Excel文档,支持xls,xlsx

粘贴Word

一键粘贴Word内容,自动上传Word中的图片,保留文字样式。

Word转图片

一键导入Word文件,并将Word文件转换成图片上传到服务器中。

导入PDF

一键导入PDF文件,并将PDF转换成图片上传到服务器中。

导入PPT

一键导入PPT文件,并将PPT转换成图片上传到服务器中。

上传网络图片

一键自动上传网络图片。

下载示例

点击下载完整示例

http://www.jsqmd.com/news/154105/

相关文章:

  • YOLOv7-Tiny性能评测:低端GPU也能流畅运行
  • YOLO模型支持Dask分布式数据处理流水线
  • YOLOv8 OBB定向边界框检测实测:旋转目标也能精准定位
  • 方达炬〖发明新字词〗:霸权丧终;霸权末世;
  • YOLO模型支持ClickHouse存储检测日志数据
  • YOLO模型支持DeepStream集成,NVIDIA Jetson完美兼容
  • YOLO目标检测支持视频流实时分析,延迟低于200ms
  • YOLO模型训练支持Gradient Accumulation应对显存不足
  • 2025年郑州比较不错的调酒培训机构推荐,有名的高性价比调酒培训学院全解析 - 工业品牌热点
  • 计算机毕业设计springboot网上商城购物系统 基于SpringBoot的线上商品交易与订单管理平台 SpringBoot+Vue的电商购物与会员服务系统
  • 2025搪瓷过滤洗涤干燥三合一生产厂家TOP5权威推荐 - 工业推荐榜
  • YOLO模型训练支持Exponential Moving Average(EMA)权重平滑
  • 2025AI创作热潮下:我如何保持技术博客的独特性|博客之星参选分享
  • 2025年昆明找工作面试服务公司推荐,找工作面试的、常见问题解析与避坑指南 - myqiye
  • YOLO在医疗影像辅助诊断中的探索:肺结节检测初探
  • YOLO在智能制造中的应用:缺陷检测与质量控制
  • YOLO模型训练过程中断续传功能上线,保障长时间任务
  • 2025年北京靠谱婚姻继承律师排行榜,有名继承法律师推荐 - 工业推荐榜
  • 2025年云南新华技能培训学校推荐:云南新华电脑学校在哪个区、云南新华单招培训相关机构有哪些? - myqiye
  • 解析 CAP 定理的物理界限:在网络分区(P)发生时,为何一致性(C)与可用性(A)不可兼得?
  • GEO优化公司怎么选?2025年避坑指南与优质服务商测评 - 品牌测评鉴赏家
  • 2025年自动门推荐厂家排名,源头自动门厂家实力解析与企业推荐 - 工业品牌热点
  • YOLO在港口集装箱识别中的应用:自动化码头新引擎
  • 电力系统潮流计算的MATLAB实现:牛顿法与P-Q分解法的探索
  • YOLO在渔业资源监测中的应用:鱼类种群数量统计
  • 【好写作AI】你的论文逻辑有“断桥”吗?让AI当你的“论证侦探”,一键排查!
  • 计算机毕设java趣味运动会管理系统 基于Java的趣味运动会综合管理系统开发 Java技术驱动的趣味运动会信息管理平台
  • 好写作AI:段落翻脸不认人?AI是你的专属“文字粘合剂”!
  • YOLOv8 Segmentation版实测:实例分割也能实时运行
  • 好写作AI:把论文“方法论”写成烹饪手册?让AI当你的专属学术主厨!