news 2026/6/20 12:55:45

wangEditor处理政府公文修订记录保留功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
wangEditor处理政府公文修订记录保留功能

📝 Word一键转存CMS升级手记

🚀 项目背景

大家好,我是江西某高校计算机专业大三的"代码狂魔",正在给我的CMS新闻管理系统做一次"整容手术"——添加Word一键转存功能!每次看到编辑部的妹子们手动复制Word内容到后台,图片还要一张张上传,我就心疼(主要是心疼她们的加班费都拿去喝奶茶了)

🕵️ 技术调研

需求拆解

  1. 前端:在wangEditor工具栏添加导入按钮
  2. 功能:支持Word/Excel/PPT/PDF → 保留格式 → 图片自动上传
  3. 兼容:Win + Mac双平台
  4. 预算:99元(毕竟学生党,得留着钱买泡面)

方案探索

方案1: mammoth.js (纯前端方案)
// 测试代码片段importmammothfrom"mammoth";mammoth.extractRawText({arrayBuffer:fileArrayBuffer}).then(function(result){console.log(result.value);// 纯文本内容}).done();

✔️ 优点:免费、轻量
❌ 缺点:只能提取文本,丢失格式和图片

方案2: docx-parser (收费)

💰 价格:$199 → 超预算!PASS!

方案3: 阿里云OSS官方SDK + phpWord
// PHP后端处理逻辑usePhpOffice\PhpWord\IOFactory;$phpWord=IOFactory::load($tempFilePath);$writer=IOFactory::createWriter($phpWord,'HTML');$writer->save('converted.html');

✔️ 优点:格式保留较好
❌ 缺点:PPT/PDF支持有限

🔧 最终方案:wangEditor + paste-extension + 自定义处理

前端实现 (Vue2)

import E from 'wangeditor' import 'wangeditor/release/wangEditor.min.css' export default { data() { return { editor: null } }, mounted() { this.initEditor() }, methods: { initEditor() { this.editor = new E(this.$refs.editor) // 自定义菜单 this.editor.config.menus = [ 'head', 'bold', 'italic', 'underline', 'strikeThrough', 'foreColor', 'backColor', 'link', 'list', 'justify', 'quote', 'table', 'code', 'undo', 'redo', 'importWord' // 自定义按钮 ] // 注册自定义按钮 this.editor.config.customAlert = (s) => { console.log(s) } this.editor.config.customMenu = { importWord: { text: '导入Office', className: 'icon-import-word', callback: () => { document.getElementById('word-upload').click() } } } this.editor.create() }, async handleFileUpload(e) { const file = e.target.files[0] if (!file) return try { const formData = new FormData() formData.append('file', file) const res = await this.$http.post('/api/office/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) this.editor.txt.html(res.data.htmlContent) } catch (error) { console.error('文件上传失败:', error) } } } }

后端处理 (PHP)

ossClient=newOSS\OssClient(getenv('OSS_ACCESS_KEY_ID'),getenv('OSS_ACCESS_KEY_SECRET'),getenv('OSS_ENDPOINT'));$this->bucketName=getenv('OSS_BUCKET');}publicfunctionhandleUpload($file){$fileExt=strtolower(pathinfo($file['name'],PATHINFO_EXTENSION));$tempPath=$file['tmp_name'];switch($fileExt){case'doc':case'docx':return$this->processWord($tempPath);case'xls':case'xlsx':return$this->processExcel($tempPath);case'ppt':case'pptx':return$this->processPpt($tempPath);case'pdf':return$this->processPdf($tempPath);default:thrownewException("不支持的格式:$fileExt");}}privatefunctionprocessWord($filePath){$phpWord=\PhpOffice\PhpWord\IOFactory::load($filePath);$htmlWriter=new\PhpOffice\PhpWord\Writer\HTML($phpWord);// 处理图片$mediaElements=$phpWord->getMediaElements();foreach($mediaElementsas$element){$imagePath=$this->uploadImageToOSS($element['source'],$element['imageExtension']);// 替换HTML中的图片路径$htmlWriter->replaceImagePath($element['mediaIndex'],$imagePath);}$htmlContent=$htmlWriter->getContent();return['htmlContent'=>$htmlContent];}privatefunctionuploadImageToOSS($binaryData,$extension){$filename='uploads/'.uniqid().'.'.$extension;$this->ossClient->putObject($this->bucketName,$filename,$binaryData);return$this->ossClient->generatePresignedUrl($this->bucketName,$filename,3600);}// 其他格式处理方法类似...}?>

🎯 开发日志

Day1: 掉坑记

  1. 尝试用纯前端方案 → 图片处理被CORS拦路抢劫
  2. 试用phpWord → 发现PPT支持是个"半成品"
  3. 喝掉三罐红牛后决定:组合拳出击!

Day3: 突破性进展

  1. 发现阿里云OSS有文件处理服务(每月免费额度够用)
  2. 结合wangEditor的paste插件魔改成功
  3. 成功保留表格样式!(虽然颜色偶尔跑偏)

💡 技术要点总结

  1. 文件处理流程

    前端上传 → 后端识别格式 → 调用对应解析器 → 提取内容+图片 → 图片上传OSS → 生成HTML → 返回编辑器
  2. 成本控制技巧

    • 使用OSS免费额度
    • 用phpWord+phpExcel+phpPowerPoint组合替代商业库
    • 图片延迟加载减少流量消耗
  3. 兼容性hack

// 处理Mac系统差异constisMac=navigator.platform.toUpperCase().indexOf('MAC')>=0;if(isMac){// 调整某些API调用方式}

📚 推荐资源

  1. PHPOffice官方文档
  2. wangEditor扩展开发指南
  3. 阿里云OSS PHP SDK示例

🍻 结语

这个项目让我深刻体会到——“程序员的时间都去哪了?全花在找免费替代方案上了!” 欢迎加入QQ群223813913一起交流,群里不定期分享:

  • 熬夜不掉头发秘诀
  • 如何用学生认证白嫖各种云服务
  • 以及…我的完整项目代码!

(注:因篇幅限制,部分代码已简化,完整实现需要处理更多边界情况。需要详细代码可以进群@我)

复制插件文件


安装jquery

npm install jquery

导入组件

importEfrom'wangeditor'const{$,BtnMenu,DropListMenu,PanelMenu,DropList,Panel,Tooltip}=Eimport{WordPaster}from'../../static/WordPaster/js/w'import{zyCapture}from'../../static/zyCapture/z'import{zyOffice}from'../../static/zyOffice/js/o'

初始化组件

//zyCapture ButtonclasszyCaptureBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyCapture.setEditor(this.editor).Capture();}tryChangeActive(){this.active()}}//zyOffice ButtonclassimportWordBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyOffice.SetEditor(this.editor).api.openDoc();}tryChangeActive(){this.active()}}//zyOffice ButtonclassexportWordBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyOffice.SetEditor(this.editor).api.exportWord();}tryChangeActive(){this.active()}}//zyOffice ButtonclassimportPdfBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){window.zyOffice.SetEditor(this.editor).api.openPdf();}tryChangeActive(){this.active()}}//WordPaster ButtonclassWordPasterBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).Paste();}tryChangeActive(){this.active()}}//wordImport ButtonclassWordImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importWord();}tryChangeActive(){this.active()}}//excelImport ButtonclassExcelImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importExcel();}tryChangeActive(){this.active()}}//ppt paster ButtonclassPPTImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importPPT();}tryChangeActive(){this.active()}}//pdf paster ButtonclassPDFImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor);WordPaster.getInstance().ImportPDF();}tryChangeActive(){this.active()}}//importWordToImg ButtonclassImportWordToImgBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor).importWordToImg();}tryChangeActive(){this.active()}}//network paster ButtonclassNetImportBtnextendsBtnMenu{constructor(editor){const$elem=E.$(`<div class="w-e-menu">`)super($elem,editor)}clickHandler(){WordPaster.getInstance().SetEditor(this.editor);WordPaster.getInstance().UploadNetImg();}tryChangeActive(){this.active()}}exportdefault{name:'HelloWorld',data(){return{msg:'Welcome to Your Vue.js App'}},mounted(){vareditor=newE('#editor');WordPaster.getInstance({//上传接口:http://www.ncmem.com/doc/view.aspx?id=d88b60a2b0204af1ba62fa66288203edPostUrl:"http://localhost:8891/upload.aspx",License2:"",//为图片地址增加域名: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:''});zyCapture.getInstance({config:{PostUrl:"http://localhost:8891/upload.aspx",License2:'',FileFieldName:"file",Fields:{uname:"test"},ImageUrl:'http://localhost:8891{url}'}})// zyoffice,// 使用前请在服务端部署zyoffice,// http://www.ncmem.com/doc/view.aspx?id=82170058de824b5c86e2e666e5be319czyOffice.getInstance({word:'http://localhost:13710/zyoffice/word/convert',wordExport:'http://localhost:13710/zyoffice/word/export',pdf:'http://localhost:13710/zyoffice/pdf/upload'})// 注册菜单E.registerMenu("zyCaptureBtn",zyCaptureBtn)E.registerMenu("WordPasterBtn",WordPasterBtn)E.registerMenu("ImportWordToImgBtn",ImportWordToImgBtn)E.registerMenu("NetImportBtn",NetImportBtn)E.registerMenu("WordImportBtn",WordImportBtn)E.registerMenu("ExcelImportBtn",ExcelImportBtn)E.registerMenu("PPTImportBtn",PPTImportBtn)E.registerMenu("PDFImportBtn",PDFImportBtn)E.registerMenu("importWordBtn",importWordBtn)E.registerMenu("exportWordBtn",exportWordBtn)E.registerMenu("importPdfBtn",importPdfBtn)//挂载粘贴事件editor.txt.eventHooks.pasteEvents.length=0;editor.txt.eventHooks.pasteEvents.push(function(){WordPaster.getInstance().SetEditor(editor).Paste();e.preventDefault();});editor.create();varedt2=newE('#editor2');//挂载粘贴事件edt2.txt.eventHooks.pasteEvents.length=0;edt2.txt.eventHooks.pasteEvents.push(function(){WordPaster.getInstance().SetEditor(edt2).Paste();e.preventDefault();return;});edt2.create();}}h1,h2{font-weight:normal;}ul{list-style-type:none;padding:0;}li{display:inline-block;margin:010px;}a{color:#42b983;}

测试前请配置图片上传接口并测试成功
接口测试
接口返回JSON格式参考

为编辑器添加按钮

components:{Editor,Toolbar},data(){return{editor:null,html:'dd',toolbarConfig:{insertKeys:{index:0,keys:['zycapture','wordpaster','pptimport','pdfimport','netimg','importword','exportword','importpdf']}},editorConfig:{placeholder:''},mode:'default'// or 'simple'}},

整合效果

导入Word文档,支持doc,docx

导入Excel文档,支持xls,xlsx

粘贴Word

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

Word转图片

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

导入PDF

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

导入PPT

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

上传网络图片

一键自动上传网络图片,自动下载远程服务器图片,自动上传远程服务器图片

下载示例

点击下载完整示例

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

wangEditor粘贴MathType公式转图片格式处理

从迷茫到突破&#xff1a;我在集团信创Word导入系统项目中的成长记 一、初遇难题&#xff1a;在技术迷宫中迷失方向&#xff08;2024年3月&#xff09; "小张&#xff0c;这个政府采购项目的标书必须在今天下班前完成格式调整&#xff01;"主管的催促声还在耳边回响…

作者头像 李华
网站建设 2026/6/19 8:12:42

搜索算法详解:从基础到高级

一、引言 搜索算法是计算机科学中最基本、最重要的算法类别之一。它们用于在数据集合中查找特定元素、寻找最优解或探索可能的路径。搜索算法的效率直接影响程序的性能,因此在各种应用场景中都有广泛的应用,包括数据库查询、路径规划、人工智能、游戏开发等。 本文将从最简单…

作者头像 李华
网站建设 2026/6/19 16:17:26

Java 读取 Excel 文件

Java 读取 Excel 文件一、前置准备&#xff1a;引入依赖方案 1&#xff1a;Apache POI&#xff08;功能全&#xff0c;兼容所有Excel版本&#xff09;方案 2&#xff1a;EasyExcel&#xff08;阿里开源&#xff0c;低内存&#xff0c;推荐大数据量&#xff09;二、方案 1&#…

作者头像 李华
网站建设 2026/6/19 16:46:17

棕榈酰三肽-38:一种“重建肌底”的智能淡纹成分

棕榈酰三肽-38&#xff1a;一种“重建肌底”的智能淡纹成分 棕榈酰三肽-38 Palmitoyl Tripeptide-38与常见的乙酰基六肽-8&#xff08;又称阿基瑞林&#xff09;作用机理完全不同&#xff0c;代表了抗老淡纹的另一种前沿思路。 核心机理对比&#xff1a; 乙酰基六肽-8&#xff…

作者头像 李华
网站建设 2026/6/18 9:31:30

高并发系统卡顿排查:全链路压测平台对比与瓶颈定位指南

核心观点摘要 1. 高并发系统卡顿问题普遍存在于电商、金融等行业&#xff0c;全链路压测是定位性能瓶颈的主流方案&#xff0c;可有效识别接口、数据库、缓存等环节异常。 2. 当前主流全链路压测平台分为SaaS化服务与私有化部署两类&#xff0c;分别在易用性、弹性成本和定…

作者头像 李华
网站建设 2026/6/19 14:14:02

12、使用WRT54G保障无线网络安全

使用WRT54G保障无线网络安全 1. 引言 无线网络安全多年来一直是计算机安全领域的热门话题。未受保护的无线网络很容易被攻破,这可能会泄露个人信息和计算机文件,还可能被用于攻击他人或进行其他不当活动。通过使用多层安全措施,特别是Wi-Fi受保护访问(WPA)或WPA2,可以降…

作者头像 李华