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

医院电子病历TinyMCE粘贴Word批注内容出现乱码怎么修复?

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/349556/

相关文章:

  • 宜春车牌靓号代选,宜春车牌靓号价格-上牌选号
  • 2026年质量好的半圆形电梯/家用圆形电梯最新TOP厂家排名 - 行业平台推荐
  • 新手也能上手,AI论文平台 千笔写作工具 VS 文途AI,MBA专属更高效!
  • 西宁车牌靓号代选,西宁车牌靓号价格-上牌选号
  • 松下 PLC FP - XH 4 轴控制程序分享:双轴直线插补实战经验
  • 探讨净化工程价格及选购要点,锦舜净化在温州靠谱吗 - myqiye
  • 2026年比较好的全拉出缓冲托底轨/V2两节缓冲托底轨厂家推荐及选择参考 - 行业平台推荐
  • The Web MCP
  • 崇左车牌靓号代选,崇左车牌靓号价格-上牌选号
  • 2026年深圳热门电子元器件回收平台排名,哪家性价比高? - 工业推荐榜
  • 摆脱论文困扰!千笔·降AIGC助手,继续教育降重首选
  • 论文写不动?AI论文软件千笔 VS Checkjie,专科生专属神器!
  • 聊聊哈尔滨财税咨询服务费用,海旭会计性价比高吗? - 工业品牌热点
  • 少走弯路:10个降AIGC工具测评,本科生降AI率必备指南
  • 2026年热门的单组份聚脲/聚脲涂料厂家选购指南与推荐 - 行业平台推荐
  • 改稿速度拉满,AI论文平台 千笔·专业论文写作工具 VS 云笔AI
  • 2026年温州口碑好的高考志愿填报企业排名,售后完善值得选 - 工业品网
  • 2026年知名的成都移动集装箱商铺/成都工地住人集装箱厂家推荐及选购指南 - 行业平台推荐
  • 剖析音乐喷泉厂家,广东广秀广场音乐喷泉服务靠谱吗 - mypinpai
  • 2026年评价高的金属波纹管设备卷管机/不锈钢金属波纹管设备厂家推荐及选择指南 - 行业平台推荐
  • 新手也能上手!降AIGC工具 千笔AI VS WPS AI,专科生专属利器!
  • 人工智能应用- 语言处理:03. 拼凑法:剪贴板式的诗人
  • 【2026】 LLM 大模型系统学习指南 (49)
  • 干货来了:圈粉无数的降AIGC平台 —— 千笔·专业降AIGC智能体
  • 计算机毕设java动物防疫信息管理系统 基于SpringBoot的家畜疫病防控信息管理平台 JavaWeb动物健康监测与防疫管理系统
  • 人工智能应用- 语言处理:04. 统计模型法:基于词频组合的诗人
  • 2026年质量好的钱币回收/钱币送评优质推荐汇总 - 行业平台推荐
  • AIGC十年演进
  • AI产品经理十年演进
  • 2026年热门的青少年冬令营/冬令营口碑优选 - 行业平台推荐