Flutter原生实现启动页与图标替换全攻略
2026/10/15 13:53:20
各位老铁好啊!我是山西那个天天跟Word文档"干仗"的前端码农,最近接了个企业官网的外包活儿,客户突然要加个"Office全家桶"功能…预算还只有680块!这不得好好跟大家唠唠我是怎么用最少的钱办最大的事儿~
客户其实就是想要个"傻瓜式"操作:
// 在setup函数里搞事情import{onMounted}from'vue'importtinymcefrom'tinymce/tinymce'import'tinymce/icons/default'import'tinymce/themes/silver'import'tinymce/plugins/paste'import'tinymce/plugins/image'exportdefault{setup(){onMounted(()=>{tinymce.init({selector:'#editor',plugins:'paste image wordcount',toolbar:'pasteword importoffice',height:800,// 自定义按钮!!!setup:(editor)=>{editor.ui.registry.addButton('pasteword',{icon:'paste',tooltip:'粘贴Word内容',onAction:()=>{navigator.clipboard.readText().then(text=>{// 这里调用咱的后端API处理Word内容fetch('/api/process-word',{method:'POST',body:JSON.stringify({content:text})}).then(res=>res.text()).then(html=>{editor.insertContent(html)})})}})// 文件导入按钮editor.ui.registry.addButton('importoffice',{text:'导入Office',onAction:()=>{// 偷偷创建一个文件inputconstinput=document.createElement('input')input.type='file'input.accept='.docx,.xlsx,.pptx,.pdf'input.onchange=(e)=>{constfile=e.target.files[0]constformData=newFormData()formData.append('file',file)fetch('/api/import-office',{method:'POST',body:formData}).then(res=>res.text()).then(html=>{editor.insertContent(html)})}input.click()}})}})})}}constexpress=require('express')constmulter=require('multer')constmammoth=require('mammoth')constsharp=require('sharp')constfs=require('fs')constapp=express()constupload=multer({dest:'uploads/'})// 处理Word粘贴app.post('/api/process-word',(req,res)=>{const{content}=req.body// 这里其实应该用mammoth处理,但演示就简单点了consthtml=content.replace(/]+src="data:image[^"]+"[^>]*>/g,match=>{// 提取base64图片constbase64Data=match.match(/src="([^"]+)"/)[1]constbuffer=Buffer.from(base64Data.split(',')[1],'base64')// 用sharp处理图片并保存constfilename=`images/${Date.now()}.jpg`sharp(buffer).resize(800)// 限制宽度.toFile(`public/${filename}`)return``})res.send(html)})// 处理Office文件导入app.post('/api/import-office',upload.single('file'),async(req,res)=>{const{path,originalname}=req.filetry{lethtmlif(originalname.endsWith('.docx')){constresult=awaitmammoth.convertToHtml({path})html=result.value}else{// 其他格式简单返回文件名(实际应该用对应的库处理)html=`已上传文件:${originalname}`}// 处理图片上传(同上)html=html.replace(/]+src="[^"]+"[^>]*>/g,match=>{// 图片处理逻辑...})res.send(html)}finally{fs.unlinkSync(path)// 删除临时文件}})app.listen(3000)公式显示问题:最终用了这个方案:
// 前端公式渲染document.querySelectorAll('.math').forEach(el=>{MathJax.typesetPromise([el]).catch(err=>{console.error('公式渲染失败:',err)})})PPT动画丢失:老老实实跟客户说做不到,加钱也做不到!(客户最后妥协了)
微信公众号特殊样式:加了这段黑魔法:
// 处理微信公众号的特殊标签html=html.replace(/]*><\/mpchecktext>/g,'')看到你们群里那个推广提成,说实话我有点心动…但我更心疼那些被忽悠的新人。这年头,什么"轻松年入40万"都是鬼扯!
我接这个680元的项目,前后改了8版需求,最后实际收入也就够交一个月房租。但是!这个案例成了我接下一个2万块项目的敲门砖——客户看到我能在这么低的预算下实现复杂功能,当场就签了合同。
所以啊,与其天天群里发广告,不如静下心来:
(小声说:那个QQ群我还是加了,领了3块钱红包就跑路了…)
最后的最后:完整项目我开源在了GitHub(其实并没有,客户不让),但核心代码都在上面了,自己拿去魔改吧!
P.S.那个公式转换的坑我填了3天3夜…你们要是遇到类似问题,记住一定要用mathjax-node,别像我一样头铁非要自己写!
在工具栏中添加插件按钮
一键粘贴Word内容,自动上传Word中的图片,保留文字样式。
一键导入Word文件,并将Word文件转换成图片上传到服务器中。
一键导入PDF文件,并将PDF转换成图片上传到服务器中。
一键导入PPT文件,并将PPT转换成图片上传到服务器中。
一键自动上传网络图片,自动下载远程服务器图片,自动上传远程服务器图片
点击下载完整示例