news 2026/4/16 4:10:18

TinyMCE6处理ppt动画效果转网页兼容

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TinyMCE6处理ppt动画效果转网页兼容

TinyMCE 文档导入插件开发方案

大家好,我是杭州的PHP程序员小张,最近接了个CMS企业官网的外包项目,客户要求在TinyMCE 5编辑器里增加Word/Excel/PPT/PDF导入功能,还要支持微信公众号内容导入。经过一番调研,我决定自己开发这个插件,毕竟预算只有680元,开源产品又满足不了需求。

插件功能概述

这个插件主要实现:

  1. 在TinyMCE工具栏添加导入按钮
  2. 支持Word/Excel/PPT/PDF文档导入
  3. 支持微信公众号内容粘贴
  4. 保留原始格式、图片、表格和公式
  5. Latex公式自动转MathML
  6. 图片自动上传到阿里云OSS

前端实现 (Vue2 + TinyMCE 5)

1. 创建插件文件src/plugins/docimport/plugin.js

(function(){constDocImport=function(editor,url){// 注册工具栏按钮editor.ui.registry.addButton('docimport',{icon:'upload',tooltip:'导入Word/Excel/PPT/PDF',onAction:function(){// 创建文件选择对话框constinput=document.createElement('input');input.type='file';input.accept='.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf';input.style.display='none';input.onchange=function(e){constfile=e.target.files[0];if(!file)return;// 显示加载中editor.setProgressState(true);// 上传文件到后端处理constformData=newFormData();formData.append('file',file);fetch(url+'/import.php',{method:'POST',body:formData}).then(response=>response.json()).then(data=>{if(data.success){// 插入处理后的HTML内容editor.insertContent(data.html);// 上传图片到OSSif(data.images&&data.images.length>0){uploadImages(editor,data.images);}}else{editor.notificationManager.open({text:'导入失败: '+data.message,type:'error'});}}).catch(error=>{editor.notificationManager.open({text:'导入过程中出错: '+error.message,type:'error'});}).finally(()=>{editor.setProgressState(false);});};document.body.appendChild(input);input.click();document.body.removeChild(input);}});// 添加粘贴处理editor.on('paste',function(e){constclipboardData=e.clipboardData||window.clipboardData;// 处理微信公众号内容if(clipboardData.types.includes('text/html')){consthtml=clipboardData.getData('text/html');if(html.includes('mp.weixin.qq.com')){e.preventDefault();processWechatContent(editor,html);return;}}// 处理Word粘贴if(clipboardData.types.includes('Files')){constitems=clipboardData.items;for(leti=0;i<items.length;i++){constitem=items[i];if(item.kind==='file'&&item.type.match(/^application\/(msword|vnd.*word|vnd.*excel|vnd.*powerpoint|pdf)/)){e.preventDefault();constfile=item.getAsFile();processPastedFile(editor,file);return;}}}});// 上传图片到OSSconstuploadImages=function(editor,images){images.forEach(imgData=>{fetch(url+'/upload.php',{method:'POST',body:JSON.stringify({image:imgData.base64,name:imgData.name}),headers:{'Content-Type':'application/json'}}).then(response=>response.json()).then(data=>{if(data.success){// 替换临时URL为OSS URLconstcontent=editor.getContent();constnewContent=content.replace(imgData.tempUrl,data.url);editor.setContent(newContent);}});});};// 处理微信公众号内容constprocessWechatContent=function(editor,html){editor.setProgressState(true);fetch(url+'/wechat.php',{method:'POST',body:JSON.stringify({html:html}),headers:{'Content-Type':'application/json'}}).then(response=>response.json()).then(data=>{if(data.success){editor.insertContent(data.html);if(data.images&&data.images.length>0){uploadImages(editor,data.images);}}else{editor.notificationManager.open({text:'处理微信公众号内容失败: '+data.message,type:'error'});}}).catch(error=>{editor.notificationManager.open({text:'处理微信公众号内容出错: '+error.message,type:'error'});}).finally(()=>{editor.setProgressState(false);});};// 处理粘贴的文件constprocessPastedFile=function(editor,file){editor.setProgressState(true);constformData=newFormData();formData.append('file',file);fetch(url+'/import.php',{method:'POST',body:formData}).then(response=>response.json()).then(data=>{if(data.success){editor.insertContent(data.html);if(data.images&&data.images.length>0){uploadImages(editor,data.images);}}else{editor.notificationManager.open({text:'导入粘贴内容失败: '+data.message,type:'error'});}}).catch(error=>{editor.notificationManager.open({text:'处理粘贴内容出错: '+error.message,type:'error'});}).finally(()=>{editor.setProgressState(false);});};};// 返回插件定义return{getMetadata:function(){return{name:'docimport',url:'https://your-plugin-site.com'};},init:DocImport};})();

2. 在Vue组件中注册插件

importEditorfrom'@tinymce/tinymce-vue';importtinymcefrom'tinymce/tinymce';import'tinymce/themes/silver';import'tinymce/plugins/image';import'tinymce/plugins/link';import'tinymce/plugins/table';// 导入我们的插件import'./plugins/docimport/plugin';exportdefault{components:{Editor},data(){return{content:'',editorInit:{height:500,menubar:true,plugins:['advlist autolink lists link image charmap print preview anchor','searchreplace visualblocks code fullscreen','insertdatetime media table paste code help wordcount','docimport'// 注册我们的插件],toolbar:'undo redo | formatselect | bold italic backcolor | \ alignleft aligncenter alignright alignjustify | \ bullist numlist outdent indent | removeformat | help | docimport',external_plugins:{'docimport':'/path/to/your/plugin.js'// 插件路径},// 其他配置...}};},mounted(){tinymce.init({});}};

后端实现 (PHP)

1. 文件导入处理import.php

'your-access-key-id','accessKeySecret'=>'your-access-key-secret','endpoint'=>'oss-cn-hangzhou.aliyuncs.com','bucket'=>'your-bucket-name','domain'=>'https://your-bucket-name.oss-cn-hangzhou.aliyuncs.com'];// 检查文件上传if(!isset($_FILES['file'])){echojson_encode(['success'=>false,'message'=>'没有上传文件']);exit;}$file=$_FILES['file'];$allowedTypes=['application/msword','application/vnd.openxmlformats-officedocument.wordprocessingml.document','application/vnd.ms-excel','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','application/vnd.ms-powerpoint','application/vnd.openxmlformats-officedocument.presentationml.presentation','application/pdf'];if(!in_array($file['type'],$allowedTypes)){echojson_encode(['success'=>false,'message'=>'不支持的文件类型']);exit;}// 临时保存文件$tempDir=sys_get_temp_dir();$tempFile=tempnam($tempDir,'docimport');move_uploaded_file($file['tmp_name'],$tempFile);// 根据文件类型调用不同的处理程序$result=[];switch($file['type']){case'application/msword':case'application/vnd.openxmlformats-officedocument.wordprocessingml.document':$result=processWord($tempFile,$ossConfig);break;case'application/vnd.ms-excel':case'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':$result=processExcel($tempFile,$ossConfig);break;case'application/vnd.ms-powerpoint':case'application/vnd.openxmlformats-officedocument.presentationml.presentation':$result=processPowerpoint($tempFile,$ossConfig);break;case'application/pdf':$result=processPdf($tempFile,$ossConfig);break;}// 删除临时文件unlink($tempFile);echojson_encode($result);// 处理Word文档functionprocessWord($filePath,$ossConfig){// 这里使用PHPWord或其它库处理Word文档// 实际项目中可以使用composer安装phpoffice/phpword// 示例代码,实际需要更复杂的处理// 简单示例:将Word转换为HTML(实际项目中需要更完善的转换)$html='导入的Word文档内容这里是转换后的内容...';// 模拟提取图片$images=[];for($i=1;$i<=3;$i++){$images[]=['base64'=>base64_encode(file_get_contents('path/to/sample-image.jpg')),'name'=>'image'.$i.'.jpg','tempUrl'=>'data:image/jpeg;base64,...'// 临时URL];}return['success'=>true,'html'=>$html,'images'=>$images];}// 处理Excel文档functionprocessExcel($filePath,$ossConfig){// 类似Word处理,使用PhpSpreadsheet等库$html='导入的Excel表格示例表格';return['success'=>true,'html'=>$html];}// 处理PowerPoint文档functionprocessPowerpoint($filePath,$ossConfig){// 处理PPT,提取每页为图片或HTML$html='导入的PPT内容幻灯片1内容';return['success'=>true,'html'=>$html];}// 处理PDF文档functionprocessPdf($filePath,$ossConfig){// 使用pdftotext或其它库提取文本和图片$html='导入的PDF内容PDF文本内容...';return['success'=>true,'html'=>$html];}?>

2. 图片上传处理upload.php

'your-access-key-id','accessKeySecret'=>'your-access-key-secret','endpoint'=>'oss-cn-hangzhou.aliyuncs.com','bucket'=>'your-bucket-name','domain'=>'https://your-bucket-name.oss-cn-hangzhou.aliyuncs.com'];// 检查输入$input=json_decode(file_get_contents('php://input'),true);if(!isset($input['image'])||!isset($input['name'])){echojson_encode(['success'=>false,'message'=>'无效的输入']);exit;}// 解码图片数据$imageData=base64_decode(preg_replace('#^data:image/\w+;base64,#i','',$input['image']));if(!$imageData){echojson_encode(['success'=>false,'message'=>'图片解码失败']);exit;}// 生成唯一文件名$extension=pathinfo($input['name'],PATHINFO_EXTENSION);$fileName='uploads/'.uniqid().'.'.$extension;// 上传到阿里云OSStry{$ossClient=new\OSS\OssClient($ossConfig['accessKeyId'],$ossConfig['accessKeySecret'],$ossConfig['endpoint']);$ossClient->putObject($ossConfig['bucket'],$fileName,$imageData);$imageUrl=$ossConfig['domain'].'/'.$fileName;echojson_encode(['success'=>true,'url'=>$imageUrl]);}catch(Exception$e){echojson_encode(['success'=>false,'message'=>'上传失败: '.$e->getMessage()]);}?>

3. 微信公众号内容处理wechat.php

'your-access-key-id','accessKeySecret'=>'your-access-key-secret','endpoint'=>'oss-cn-hangzhou.aliyuncs.com','bucket'=>'your-bucket-name','domain'=>'https://your-bucket-name.oss-cn-hangzhou.aliyuncs.com'];// 检查输入$input=json_decode(file_get_contents('php://input'),true);if(!isset($input['html'])){echojson_encode(['success'=>false,'message'=>'无效的输入']);exit;}$html=$input['html'];// 清理微信公众号HTML$dom=newDOMDocument();@$dom->loadHTML(''.$html);$dom->encoding='UTF-8';// 提取主要内容,去除不必要的标签$resultHtml='';$body=$dom->getElementsByTagName('body')->item(0);if($body){// 处理图片$images=$body->getElementsByTagName('img');$imageList=[];foreach($imagesas$img){$src=$img->getAttribute('src');if(strpos($src,'data:image')===0){// base64图片,需要上传$imageData=base64_decode(preg_replace('#^data:image/\w+;base64,#i','',$src));if($imageData){$extension='jpg';// 默认jpg$fileName='wechat/'.uniqid().'.'.$extension;try{$ossClient=new\OSS\OssClient($ossConfig['accessKeyId'],$ossConfig['accessKeySecret'],$ossConfig['endpoint']);$ossClient->putObject($ossConfig['bucket'],$fileName,$imageData);$imageUrl=$ossConfig['domain'].'/'.$fileName;$img->setAttribute('src',$imageUrl);$imageList[]=['tempUrl'=>$src,'base64'=>base64_encode($imageData),'name'=>basename($fileName)];}catch(Exception$e){// 上传失败,保留原图}}}}// 处理公式(简单示例,实际需要更复杂的处理)$resultHtml=$dom->saveHTML();// 清理微信特有的类名和样式$resultHtml=preg_replace('/class="[^"]*mp-weixin[^"]*"/i','',$resultHtml);$resultHtml=preg_replace('/style="[^"]*"/i','',$resultHtml);}echojson_encode(['success'=>true,'html'=>$resultHtml,'images'=>$imageList]);?>

部署说明

  1. 前端部署

    • 将插件文件放在Vue项目的public/plugins/docimport/目录下
    • 在TinyMCE初始化配置中正确设置external_plugins路径
  2. 后端部署

    • 将PHP文件放在服务器可访问的目录
    • 安装必要的PHP扩展(如fileinfo)
    • 通过Composer安装阿里云OSS SDK:composer require alibabacloud/sdk
    • 配置正确的OSS访问权限
  3. 数据库

    • 本插件不需要额外的数据库表
    • 如果需要记录导入日志,可以创建简单的日志表

预算控制

这个方案完全在680元预算内:

  • 主要成本是阿里云OSS的存储费用(几乎可以忽略)
  • 开发时间约20-30小时(按杭州IT行业平均时薪计算,远低于预算)
  • 使用了开源库(TinyMCE、PHPWord等),没有额外授权费用

群内推广

兄弟们,这个插件我已经开发得差不多了,测试通过后就可以打包成开箱即用的版本。欢迎大家加群223813913一起交流:

  • 可以代理销售这个插件
  • 可以合作开发类似的企业级插件
  • 可以分享外包项目资源

新人加群送1-99元红包,推荐客户成交提成20%,这钱赚得轻松又舒服!

注意事项

  1. 实际项目中需要根据需求调整文档转换的精度
  2. 对于复杂的公式和样式,可能需要更专业的文档处理库
  3. 生产环境需要添加更多的错误处理和日志记录
  4. 需要考虑安全性,如文件类型验证、大小限制等

这个方案应该能满足客户的需求,特别是对高龄用户友好的一键粘贴功能,能显著提高内容发布效率。大家如果有更好的实现方式或者遇到问题,欢迎在群里讨论!

复制插件

安装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转换成图片上传到服务器中。

上传网络图片

一键自动上传网络图片。

下载示例

点击下载完整示例

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 4:09:24

基于java的SpringBoot/SSM+Vue+uniapp的四六级学习资料管理系统的详细设计和实现(源码+lw+部署文档+讲解等)

文章目录 前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus 系统测试系统测试目的系统功能测试系统测试结论 为什么选择我代码参考数据库参考源码获取 前言 &#x1f31e;博主介绍&#xff1a;✌全网粉丝15W,CSDN特邀作者、211毕业、高…

作者头像 李华
网站建设 2026/4/13 0:34:41

Flutter深度实战:从原理到进阶的跨平台开发全攻略

Flutter深度实战&#xff1a;从原理到进阶的跨平台开发全攻略 一、引言&#xff1a;为什么选择Flutter&#xff1f; 在移动开发领域&#xff0c;开发者长期面临两大痛点&#xff1a;原生开发成本高&#xff08;需同时维护Android/iOS两套代码&#xff09;和跨平台方案性能不足…

作者头像 李华
网站建设 2026/4/14 10:25:35

14、psad:检测与防范网络可疑流量

psad:检测与防范网络可疑流量 1. 不同扫描类型的特征与检测 1.1 TCP 选项特征 在 Nmap SYN 扫描中,TCP 报头的选项部分显著缩短。它通常仅使用一个选项,即最大段大小(Maximum Segment Size),并将其设置为 1460。而大多数真实的 TCP 栈除最大段大小外,还会发送多个选项…

作者头像 李华
网站建设 2026/4/13 5:29:05

21、深入解析Snort规则转换为iptables规则及fwsnort部署

深入解析Snort规则转换为iptables规则及fwsnort部署 1. 不支持的Snort规则选项 虽然iptables能在很大程度上模拟Snort规则语言,但仍有许多Snort选项在iptables中没有很好的等效项。部分选项可通过iptables的u32扩展模拟,待u32扩展移植到2.6内核后,fwsnort的后续版本将支持…

作者头像 李华
网站建设 2026/4/15 23:17:44

next-ai-draw-io:下一代AI辅助的Draw.io图表绘制神器

在AI技术重塑应用格局的时代&#xff0c;智能图表绘制工具正逐渐成为技术文档编写、系统设计与团队协作中不可或缺的利器。过去我常使用 draw.io 制作图表&#xff0c;而最近在 GitHub 上发现了一个为 draw.io 集成 AI 能力的项目——这无疑是为这款工具插上了智能的翅膀。今天…

作者头像 李华
网站建设 2026/4/9 16:10:02

AI依赖对学生学习影响的量化评估研究框架

个人首页&#xff1a; VON 鸿蒙系列专栏&#xff1a; 鸿蒙开发小型案例总结 综合案例 &#xff1a;鸿蒙综合案例开发 鸿蒙6.0&#xff1a;从0开始的开源鸿蒙6.0.0 鸿蒙5.0&#xff1a;鸿蒙5.0零基础入门到项目实战 本文章所属专栏&#xff1a;《AI从0到1&#xff1a;普通人…

作者头像 李华