信创国产化CMS如何改造TinyMCE4实现微信文章图片的局域网粘贴上传与国产加密?

TinyMCE插件实现文档智能导入与图片上传

江苏.NET程序员的CMS文档神器(680元保姆级方案)

“各位老铁,最近接了个企业官网外包项目,客户爸爸非要让我给TinyMCE编辑器加上Word/Excel/PPT/PDF导入功能,还要支持微信公众号内容粘贴。预算只有680元,但需求比我的头发还密集——不过别慌,本程序员最擅长在刀尖上跳舞(毕竟头发掉光了也不怕)!”


一、方案亮点(打工人友好版)

  • 开箱即用:解压即插,TinyMCE工具栏秒变「文档神器」按钮(亲测Vue3兼容)
  • 全格式通吃:Word/Excel/PPT/PDF/公众号内容全覆盖(WPS粘Word也不崩)
  • 公式高清:Latex自动转MathML,手机/平板/小程序都能高清显示(实测iPhone 14 Pro Max没问题)
  • 预算友好:680元买断源码(含部署教程),终身免费升级(比奶茶还划算!)
  • 集成简单:复制粘贴就能用,不影响现有系统(客户说「这钱花得值」)

二、前端实现(TinyMCE插件集成)

1. 插件目录结构(直接丢进TinyMCE的plugins文件夹)

/tiny-mce/plugins/doc_magic/
├─ dialog.html          # 多功能操作面板(Vue3适配版)
├─ doc_magic.js         # 核心插件逻辑(超简单,就200行)
└─ style.css            # 样式文件(兼容IE8+)

2. 核心代码(doc_magic.js)—— 学长亲自写的,注释超详细

// 注册TinyMCE插件(Vue3/React通用,复制就能用)
tinymce.PluginManager.add('doc_magic', function(editor, url) {
    // 创建万能按钮(用了阿里云同款绿,好看!)
    const btn = editor.ui.registry.addButton('doc_magic', {
        icon: 'document',
        tooltip: '文档神器(粘贴/导入)',
        onAction: () => showMagicDialog(editor) // 点击触发弹窗
    });

    // 显示多功能弹窗(Vue3轻量适配,不影响现有系统)
    function showMagicDialog(editor) {
        editor.windowManager.open({
            title: '文档导入神器(打工人亲测)',
            width: 900,
            height: 650,
            body: {
                type: 'tabpanel',
                tabs: [{
                    title: '粘贴内容',
                    items: [{
                        type: 'textarea',
                        name: 'pasteContent',
                        label: '粘贴Word/公众号内容(Ctrl+V)',
                        multiline: true,
                        maxHeight: 300
                    }, {
                        type: 'button',
                        text: '提取内容(打工人推荐)',
                        onclick: () => processPaste(editor) // 处理粘贴
                    }, {
                        type: 'htmlpanel',
                        htmlId: 'pastePreview' // 预览区域
                    }]
                }, {
                    title: '导入文档',
                    items: [{
                        type: 'filepicker',
                        name: 'fileUpload',
                        label: '选文件(支持docx/xlsx/pptx/pdf)',
                        onchange: (e) => handleFileUpload(e, editor) // 处理上传
                    }, {
                        type: 'htmlpanel',
                        htmlId: 'filePreview' // 预览区域
                    }]
                }, {
                    title: '公众号导入',
                    items: [{
                        type: 'textbox',
                        name: 'wechatUrl',
                        label: '公众号文章链接(例:https://mp.weixin.qq.com/...)',
                        maxWidth: 500
                    }, {
                        type: 'button',
                        text: '抓取内容(打工人实测可用)',
                        onclick: () => fetchWechatContent(editor) // 抓取公众号
                    }, {
                        type: 'htmlpanel',
                        htmlId: 'wechatPreview' // 预览区域
                    }]
                }]
            },
            buttons: [{
                type: 'cancel',
                text: '关闭(打工人说别点这个)'
            }]
        });
    }

    // 处理粘贴内容(图片自动上传OSS,保留样式)
    async function processPaste(editor) {
        const content = tinymce.activeEditor.dom.get('pasteContent').value;
        // 调用后端API(ASP.NET WebForm写的,超简单)
        const res = await fetch('/api/doc/process-paste', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({ content })
        });
        const data = await res.json();
        tinymce.activeEditor.dom.get('pastePreview').innerHTML = data.content; // 显示预览
    }

    // 处理文件上传(自动上传图片到OSS)
    async function handleFileUpload(e, editor) {
        const file = e.target.files[0];
        const formData = new FormData();
        formData.append('file', file);
        
        // 调用后端上传接口(ASP.NET处理OSS上传)
        const res = await fetch('/api/doc/upload-file', {
            method: 'POST',
            body: formData
        });
        const data = await res.json();
        tinymce.activeEditor.dom.get('filePreview').innerHTML = data.content; // 显示预览
    }

    // 抓取公众号内容(自动下载图片)
    async function fetchWechatContent(editor) {
        const url = tinymce.activeEditor.dom.get('wechatUrl').value;
        const res = await fetch('/api/doc/fetch-wechat', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({ url })
        });
        const data = await res.json();
        tinymce.activeEditor.dom.get('wechatPreview').innerHTML = data.content; // 显示预览
    }
});

3. 操作面板(dialog.html)—— 打工人设计的,颜值在线




    文档神器(打工人版)
    
    
    


    
        
    

    
        // 兼容老浏览器的DOM操作(打工人加的,防止IE8崩)
        function getElementsByClassName(className) {
            return document.querySelectorAll('.' + className);
        }
    



三、后端实现(ASP.NET WebForm)—— 打工人用VS2022搭的,超省心

1. 环境准备(宿舍电脑/实验室服务器都能跑)

  • Windows 10/Server 2019(推荐Win10,开发调试方便)
  • Visual Studio 2022(社区版免费,打工人用的是这个)
  • .NET Framework 4.8(WebForm最佳拍档)
  • SQL Server 2019(打工人用的是阿里云RDS,免费版够用)
  • 阿里云OSS SDK(Install-Package Aliyun.OSS.SDK.NetCore -Version 3.15.1

2. OSS配置(Web.config)—— 打工人写死的,直接填你的OSS信息


  
    
    
    
    
  

3. 核心处理类(App_Code/DocProcessor.cs)—— 打工人写的,注释超详细

using System;
using System.IO;
using System.Text.RegularExpressions;
using Aliyun.OSS;
using Microsoft.Office.Interop.Word; // 需安装Office(打工人用WPS替代)
using Aspose.Words; // 免费库,需自行下载(打工人用的是免费版)

public class DocProcessor {
    // OSS配置(从Web.config读)
    private static string ossEndpoint = ConfigurationManager.AppSettings["OSS_Endpoint"];
    private static string ossAccessKey = ConfigurationManager.AppSettings["OSS_AccessKey"];
    private static string ossSecret = ConfigurationManager.AppSettings["OSS_Secret"];
    private static string ossBucket = ConfigurationManager.AppSettings["OSS_Bucket"];

    // 处理粘贴的Word内容(图片上传OSS,保留样式)
    public string ProcessPastedWord(string html) {
        // 1. 清理Word垃圾标签(打工人实测有效)
        string cleanHtml = CleanWordTags(html);
        
        // 2. 提取并上传图片(二进制存储,非Base64)
        cleanHtml = UploadImages(cleanHtml);
        
        // 3. 转换Latex为MathML(调用MathJax免费API)
        cleanHtml = ConvertLatexToMathML(cleanHtml);
        
        return cleanHtml;
    }

    // 解析Word文档(.docx)
    public string ParseWord(string filePath) {
        // 打工人用Aspose.Words(免费版)解析,比Office Interop更稳定
        Document doc = new Document(filePath);
        StringBuilder html = new StringBuilder("");

        // 处理段落(保留字体/字号/颜色)
        foreach (Paragraph para in doc.Paragraphs) {
            html.Append("");
            foreach (Run run in para.Runs) {
                html.Append("");
                html.Append(run.Text);
                html.Append("");
            }
            html.Append("");
        }

        // 处理表格(保留形状组)
        foreach (Table table in doc.Tables) {
            html.Append("");
            foreach (Row row in table.Rows) {
                html.Append("");
                foreach (Cell cell in row.Cells) {
                    html.Append("");
                }
                html.Append("");
            }
            html.Append("").Append(ParseCell(cell)).Append("");
        }

        html.Append("");
        return html.ToString();
    }

    // 辅助方法:清理Word垃圾标签(打工人调了3晚的bug!)
    private string CleanWordTags(string html) {
        return Regex.Replace(html, @".*?", "", RegexOptions.Singleline)
                    .Replace("class=""MsoNormal""", "")
                    .Replace("]+src=""data:image/(png|jpg);base64,(.*?)""[^>]*>");
        foreach (Match match in matches) {
            string base64 = match.Groups[2].Value;
            byte[] bytes = Convert.FromBase64String(base64);
            string tempPath = Path.GetTempFileName() + ".png";
            File.WriteAllBytes(tempPath, bytes);

            // 上传到OSS(打工人写的方法,超简单)
            string ossUrl = UploadToOSS(tempPath, "paste_img_" + DateTime.Now.Ticks + ".png");
            html = html.Replace(match.Value, $"");
            File.Delete(tempPath); // 删除临时文件
        }
        return html;
    }

    // 辅助方法:上传文件到OSS(打工人封装的,超好用)
    private string UploadToOSS(string filePath, string fileName) {
        OssClient ossClient = new OssClient(ossEndpoint, ossAccessKey, ossSecret);
        string objectKey = $"cms_docs/{fileName}"; // 存储路径:cms_docs/文件名
        
        try {
            ossClient.PutObject(ossBucket, objectKey, new FileStream(filePath, FileMode.Open));
            return $"https://{ossBucket}.{ossEndpoint}/{objectKey}";
        } catch (Exception ex) {
            return $"上传失败:{ex.Message}";
        }
    }

    // 辅助方法:Latex转MathML(调用MathJax免费API)
    private string ConvertLatexToMathML(string html) {
        return Regex.Replace(html, @"\$(.*?)\$", match => {
            string latex = match.Groups[1].Value;
            try {
                // 调用MathJax API(免费,实测可用)
                string mathml = new WebClient().DownloadString($"https://mathjax.github.io/MathJax-demos-web/convert-latex-to-mathml/?latex={latex}");
                return mathml.Contains(" false;
}

四、部署指南(打工人手把手教,5分钟搞定)

1. 环境搭建(宿舍电脑/实验室服务器)

  1. 安装Windows 10/Server 2019(推荐Win10,开发调试方便)
  2. 安装Visual Studio 2022(社区版免费,https://visualstudio.microsoft.com/zh-hans/vs/)
  3. 安装.NET Framework 4.8(https://dotnet.microsoft.com/download/dotnet-framework/net48)
  4. 安装SQL Server 2019(https://dev.mysql.com/downloads/mysql/,打工人用的是阿里云RDS)
  5. 注册阿里云OSS(https://oss.console.aliyun.com/),创建Bucket并获取AccessKey

2. 集成步骤(复制粘贴就能用)

  1. doc_magic插件文件夹丢进TinyMCE的plugins目录(路径:tinymce/plugins/
  2. 在TinyMCE初始化配置(tinymce.init.js)中添加按钮:
    tinymce.init({
        selector: '#editor',  // 你的编辑器容器ID
        plugins: 'doc_magic', // 添加插件
        toolbar: 'doc_magic bold italic' // 工具栏显示按钮
    });
    
  3. Web.config中的OSS信息改成你自己的(阿里云控制台获取)
  4. 把项目发布到IIS(发布IIS、FTP等选择服务器

五、群组福利(打工人建的,专搞外包)

加群223813913,解锁以下隐藏福利:

  • 新人红包:1~99元随机现金(手慢无!打工人自己发的)
  • 接单特权:优先获取企业CMS外包项目(单价1k~5k,打工人带飞)
  • 提成暴击:推荐客户拿20%提成(1万订单直接拿2k!打工人算过,一个月接5单够生活费)
  • 内推通道:打工人在上海软件园有资源,国企/事业单位技术岗直推(月薪8k+)

群友真实反馈:“上周推荐了个政府项目,提成拿了3k,够买台新笔记本了!”


四、薅羊毛与避坑指南

  1. 免费资源

    • 阿里云OSS临时授权(领用地址:aliyun.com/activity/oss-free
    • Visual Studio 2022社区版(白嫖永久授权)
    • 群福利:输入暗号"企业官网救我"领:
      ✅ 完整插件包
      ✅ OSS上传Demo
      ✅ 公式转换工具
      ✅ 客户催稿应对话术
  2. 预算控制

    • 插件费用:$49(约350元)
    • 阿里云OSS流量:预计$5(约35元)
    • 剩余预算:$17(买咖啡续命)

五、求职与外包彩蛋

"顺便问下,有南京/苏州的.NET岗位吗?本人技能树:
✔️ 精通Ctrl+C/V
✔️ 熟练百度Stack Overflow
✔️ 擅长在GitHub找付费插件
✔️ 阿里云ECS部署经验+1

(附简历链接:github.com/your-name/resume)"


最终效果
客户测试时惊呼:“这Word粘贴比我老婆的复制粘贴还智能!”
我淡定回复:“基本操作,坐下~”(实际在群里疯狂@大佬求救)

(群公告:新人红包已就位!推荐客户提20%,黄金会员提50%!错过这村……我就去你家门口贴小广告!)

源代码包

(群号:223813913,暗号"企业官网救我"领红包!PS:本群主已靠推荐提成喜提奶茶自由~)

复制插件

WordPaster插件文件夹

安装jquery

npm install jquery

在组件中引入

  // 引入tinymce-vue
  import Editor from '@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';
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    function selectLocalImages(editor) {        
      WordPaster.getInstance().SetEditor(editor).importExcel()
    }

    var register$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)
        }
      });
    };
    var Buttons = { register: register$1 };
    function Plugin () {
      global.add('excelimport', function (editor) {        
        Buttons.register(editor);
      });
    }
    Plugin();
}());

//添加word转图片工具栏按钮
(function () {
    'use strict';
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    function selectLocalImages(editor) {        
      WordPaster.getInstance().SetEditor(editor);
      WordPaster.getInstance().importWordToImg()
    }

    var register$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)
        }
      });
    };
    var Buttons = { register: register$1 };
    function Plugin () {
      global.add('importwordtoimg', function (editor) {        
        Buttons.register(editor);
      });
    }
    Plugin();
}());

//添加粘贴网络图片工具栏按钮
(function () {
    'use strict';
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    function selectLocalImages(editor) {        
      WordPaster.getInstance().SetEditor(editor);
      WordPaster.getInstance().UploadNetImg()
    }

    var register$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)
        }
      });
    };
    var Buttons = { register: register$1 };
    function Plugin () {
      global.add('netpaster', function (editor) {        
        Buttons.register(editor);
      });
    }
    Plugin();
}());

//添加导入PDF按钮
(function () {
    'use strict';
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    function selectLocalImages(editor) {        
      WordPaster.getInstance().SetEditor(editor);
      WordPaster.getInstance().ImportPDF()
    }

    var register$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)
        }
      });
    };
    var Buttons = { register: register$1 };
    function Plugin () {
      global.add('pdfimport', function (editor) {        
        Buttons.register(editor);
      });
    }
    Plugin();
}());

//添加导入PPT按钮
(function () {
    'use strict';
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    function selectLocalImages(editor) {        
      WordPaster.getInstance().SetEditor(editor);
      WordPaster.getInstance().importPPT()
    }

    var register$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)
        }
      });
    };
    var Buttons = { register: register$1 };
    function Plugin () {
      global.add('pptimport', function (editor) {        
        Buttons.register(editor);
      });
    }
    Plugin();
}());

//添加导入WORD按钮
(function () {
    'use strict';
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    function selectLocalImages(editor) {        
      WordPaster.getInstance().SetEditor(editor).importWord()
    }

    var register$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)
        }
      });
    };
    var Buttons = { register: register$1 };
    function Plugin () {
      global.add('wordimport', function (editor) {        
        Buttons.register(editor);
      });
    }
    Plugin();
}());

//添加WORD粘贴按钮
(function () {
    'use strict';
    var global = tinymce.util.Tools.resolve('tinymce.PluginManager');
    var ico = "http://localhost:8080/static/WordPaster/plugin/word.png"
    function selectLocalImages(editor) {
      WordPaster.getInstance().SetEditor(editor).PasteManual()
    }

    var register$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)
        }
      });
    };
    var Buttons = { register: register$1 };
    function Plugin () {
      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=d88b60a2b0204af1ba62fa66288203ed
    PostUrl: 'http://localhost:8891/upload.aspx',
    // 为图片地址增加域名:http://www.ncmem.com/doc/view.aspx?id=704cd302ebd346b486adf39cf4553936
    ImageUrl: 'http://localhost:8891{url}',
    // 设置文件字段名称:http://www.ncmem.com/doc/view.aspx?id=c3ad06c2ae31454cb418ceb2b8da7c45
    FileFieldName: 'file',
    // 提取图片地址:http://www.ncmem.com/doc/view.aspx?id=07e3f323d22d4571ad213441ab8530d1
    ImageMatch: ''
})

在页面中引入组件


功能演示

编辑器

在编辑器中增加功能按钮
WordPaster-TinyMCE5

导入Word文档,支持doc,docx

粘贴Word和图片

导入Excel文档,支持xls,xlsx

粘贴Word和图片

粘贴Word

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

Word转图片

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

导入PDF

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

导入PPT

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

上传网络图片

一键自动上传网络图片。
自动上传网络图片

下载示例

点击下载完整示例

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值