尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

我用微信小程序做了一个工具箱:从 0 到上线的完整记录

发布时间:2026/9/16 7:43:36

资讯中心
01
ARTICLE

我用微信小程序做了一个工具箱:从 0 到上线的完整记录

我用微信小程序做了一个工具箱:从 0 到上线的完整记录
没有用任何框架纯原生 npm 包9 个实用工具一套墨蓝仪表盘 UI。本文完整记录从需求分析到发布的全过程附带核心代码。文末有体验入口欢迎扫码试用。为什么做这个小程序事情很简单——我做了 15 年前端开发日常工作中总有一些小需求反复出现客户发来一段 JSON需要快速格式化看看结构对不对要把一个链接转成二维码发到群里让别人扫前端收到后端的时间戳要看看对应什么时间吃饭 AA 分账算每人该出多少钱这些需求不需要装 App但每次都要打开某个网页、等加载、甚至有时候网络不好还打不开。我就想能不能在微信里一键解决不用下载、不用注册、用完即走——这正是微信小程序的天然优势。目前已经上线包含 9 个工具分 3 大类图像工具图片压缩、二维码生成开发工具时间戳转换、JSON 格式化、Base64 编解码、MD5/SHA 哈希其他工具AA 分账、日期计算、单位换算一、技术选型为什么坚持用原生市面上做小程序的方案很多Uni-app、Taro、Remax……但我最终选了纯原生微信小程序开发。原因很实际工具类小程序没有复杂状态管理——不需要 Vuex/Redux 那套东西每个工具页独立运行——页面之间几乎没有数据共享需求性能优先——原生 Canvas 2D API 做二维码渲染没有中间层损耗包体积控制——没有框架运行时开销整个小程序打包后非常轻量项目结构也很干净workjob/ ├── app.js # 最小入口 ├── app.json # 页面注册 TabBar 配置 ├── app.wxss # CSS 变量设计令牌中心 ├── pages/ │ ├── index/ # 首页工具箱导航 │ ├── resume/ # 关于我个人主页 │ ├── compress/ # 图片压缩 │ ├── qrcode/ # 二维码生成 │ ├── timestamp/ # 时间戳转换 │ ├── jsonfmt/ # JSON 格式化 │ ├── base64/ # Base64 编解码 │ ├── hash/ # MD5/SHA 哈希 │ ├── split/ # AA 分账 │ ├── datecalc/ # 日期计算 │ └── unitconvert/ # 单位换算 └── utils/ ├── resume-data.js # 简历数据源数据驱动 └── weapp-qrcode.js # 二维码生成库一个原则每个工具一个页面目录结构统一维护成本极低。二、UI 设计墨蓝仪表盘风格大多数工具箱小程序都长一个样——白底、圆角卡片、蓝色按钮。我想做点不一样的。我的日常工作是在能源行业做前端做的是充电站运营平台、物联网数据大屏。那种墨蓝底色 电光橙高亮的仪表盘界面看多了觉得很酷——为什么工具箱不能是这个风格CSS 变量设计令牌所有颜色集中在app.wxss里用 CSS 变量管理page{--ink:#1B2A4A;/* 墨蓝标题、导航栏 */--ink-2:#24365E;/* 墨蓝浅档 */--paper:#F4F6F9;/* 冷调纸白页面底色 */--card:#FFFFFF;/* 内容卡片 */--volt:#FF5A1F;/* 电光橙唯一强调色 */--volt-2:#FFB100;/* 琥珀渐变起点 */--mist:#8A94A6;/* 灰蓝次要文字 */--line:#E3E8EF;/* 分隔线 */--font-num:DIN Alternate,Bahnschrift,monospace;--font-body:-apple-system,PingFang SC,sans-serif;}这样做的好处改一处全局生效——要调色调只改变量暗色模式好扩展——后面加media (prefers-color-scheme: dark)覆盖变量就行团队协作友好——看到--volt就知道是强调色不用猜#FF5A1F是什么字体分工数字用 DIN Alternate工业仪表盘感中文用苹方/思源。在 CSS 里做了强制分工.din{font-family:var(--font-num);}需要显示数字的地方套一个.din类自动切到数字字体。三、首页设计数据驱动的导航首页是用户进来的第一屏。我的想法是分类清晰、一触即达、支持后续扩展。数据结构工具列表不走硬编码而是用一个数组结构来渲染// pages/index/index.jsPage({data:{categories:[{title:图像工具,tools:[{name:图片压缩,icon:/images/tit1_ico1.png},{name:二维码生成,icon:/images/tit1_ico2.png}]},{title:开发工具,tools:[{name:时间戳转换,icon:/images/tit2_ico4.png},{name:JSON 格式化,icon:/images/tit2_ico5.png},{name:Base64 编解码,icon:/images/tit2_ico6.png},{name:MD5/SHA 哈希,icon:/images/tit2_ico7.png}]},{title:其他工具,tools:[{name:AA分账,icon:/images/tit2_ico1.png},{name:日期计算,icon:/images/tit2_ico2.png},{name:单位换算,icon:/images/tit2_ico3.png}]}]}})新增工具只需要在categories数组里加一项不需要改布局模板。跳转逻辑点击工具后根据name判断跳转到哪个页面onToolTap(e){constnamee.currentTarget.dataset.nameconstrouteMap{图片压缩:/pages/compress/index,二维码生成:/pages/qrcode/index,时间戳转换:/pages/timestamp/index,JSON 格式化:/pages/jsonfmt/index,Base64 编解码:/pages/base64/index,MD5/SHA 哈希:/pages/hash/index,AA分账:/pages/split/index,日期计算:/pages/datecalc/index,单位换算:/pages/unitconvert/index,}if(routeMap[name]){wx.navigateTo({url:routeMap[name]})}else{wx.showToast({title:敬请期待,icon:none})}}用路由映射表替代一长串if-else新增工具时只要在routeMap里加一行。 实际代码中我最初用的是if-else后来重构成了映射表。这也是一个很实用的优化——当你发现条件分支超过 5 个就该考虑用对象映射替代了。*底部 TabBar两个 Tab首页工具箱关于我个人主页。{tabBar:{color:#8A94A6,selectedColor:#FF5A1F,backgroundColor:#1B2A4A,list:[{pagePath:pages/index/index,text:首页},{pagePath:pages/resume/resume,text:关于我}]}}TabBar 底色用墨蓝选中色用电光橙跟整体风格统一。四、核心工具开发实录挑几个有代表性的工具讲讲实现细节和踩坑。工具 1二维码生成 —— Canvas 2D 的坑这是我最满意的一个工具。支持自定义颜色、Logo、一键保存。技术难点微信小程序的 Canvas 经历过从Canvas 1.0到Canvas 2.0的大改。旧版wx.createCanvasContext已经废弃新版要用Canvas 2D原生 API。我用的weapp-qrcode库但它的内部实现还是基于旧版 Canvas API。怎么兼容方案拦截绘制指令用新 API 重绘。constQRrequire(../../utils/weapp-qrcode.js)Page({onGenerate(){constthatthisconstquerywx.createSelectorQuery()query.select(#qrCanvas).fields({node:true}).exec((res){if(!res||!res[0]||!res[0].node){wx.showToast({title:Canvas 未就绪,icon:none})return}constcanvasres[0].nodeconstctxcanvas.getContext(2d)// 第一步用假 ctx 收集所有绘制指令constcommands[]letcurrentColorthat.data.backgroundColorconstfakeCtx{setFillStyle(c){currentColorc},fillRect(x,y,w,h){commands.push({x,y,w,h,color:currentColor})},drawImage(src,dx,dy,dw,dh){commands.push({type:img,src,dx,dy,dw,dh})},draw(_,cb){if(cb)cb()}}// 调用库生成 QR 矩阵但不真正绘制QR({ctx:fakeCtx,width:size,height:size,text:that.data.text.trim(),correctLevel:0,foreground:that.data.foregroundColor,background:that.data.backgroundColor,image:that.data.hasLogo?that.data.logoPath:})// 第二步用 Canvas 2D API 真正重绘canvas.widthsize canvas.heightsize ctx.fillStylethat.data.backgroundColor ctx.fillRect(0,0,size,size)for(constcmdofcommands){if(cmd.typeimg){// 处理 Logo 图片constimgcanvas.createImage()img.onload(){ctx.drawImage(img,cmd.dx,cmd.dy,cmd.dw,cmd.dh)that._exportQR(canvas,size)}img.srccmd.src}else{ctx.fillStylecmd.color ctx.fillRect(cmd.x,cmd.y,cmd.w,cmd.h)}}})}})这个指令拦截 重绘的方案是核心亮点不修改第三方库源码兼容新旧 Canvas API可以任意扩展比如加圆角、渐变、阴影配色预设我做了 6 套配色方案用户可以一键切换constCOLOR_PRESETS[{fg:#000000,bg:#FFFFFF,label:经典},{fg:#1B2A4A,bg:#F4F6F9,label:墨蓝},{fg:#FF5A1F,bg:#FFFFFF,label:电光橙},{fg:#000000,bg:#FFB100,label:琥珀},{fg:#3DDC84,bg:#000000,label:赛博},{fg:#6366F1,bg:#FFFFFF,label:紫罗兰}]生成的二维码可以直接保存到手机相册方便转发。工具 2JSON 格式化 —— 容错的艺术开发者最常用到的工具。除了常规的美化和压缩我加了一个关键特性JS 对象语法兼容。痛点开发中经常遇到这种情况后端或同事发来的 JSON 是 JS 对象格式——单引号、无引号属性名、尾逗号直接JSON.parse会报错。// 这不是合法 JSON但开发者经常遇到{name:test,tags:[a,b,],}解决方案四层降级解析_format(beautify){consttextthis.data.inputText.trim()letobjnullletusedFallbackfalse// 第一层标准 JSON.parsetry{objJSON.parse(text)}catch(e){// 第二层JS 对象语法转 JSON 后再解析try{constjsonTextthis._jsToJson(text)objJSON.parse(jsonText)usedFallbacktrue}catch(e2){// 第三层尝试用 {} 包裹后解析try{objJSON.parse({text})usedFallbacktrue}catch(e3){// 第四层{} 包裹 JS 转换try{objJSON.parse(this._jsToJson({text}))usedFallbacktrue}catch(e4){this.setData({errorMsg:this._formatError(e.message,text)})return}}}}constoutputbeautify?JSON.stringify(obj,null,2):JSON.stringify(obj)// 渲染输出...}四层降级解析策略标准 JSON → JS 转换 → 自动包裹 → JS 转换 包裹能处理绝大多数“不规范 JSON”的情况况。_jsToJson转换逻辑_jsToJson(text){letstext// 移除注释ss.replace(/\/\/.*$/gm,)ss.replace(/\/\*[\s\S]*?\*\//g,)// 单引号转双引号ss.replace(/([^\\]*(?:\\.[^\\]*)*)/g,$1)// 无引号属性名加双引号ss.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,$1$2:)// 移除尾逗号ss.replace(/,\s*([}\]])/g,$1)// 移除 undefined / functionJSON 不支持ss.replace(/:\s*undefined\b/g,: null)ss.replace(/:\s*function\s*\([^)]*\)\s*\{[^}]*\}/g,: null)returns}附加功能JSON 路径查询格式化后可以直接查询某个字段的值onQuery(){constpaththis.data.queryPath.trim()// 将 categories[0].tools[0].name 转为 categories.0.tools.0.nameconstnormalizedPathpath.replace(/\[(\d)\]/g,.$1)constkeysnormalizedPath.split(.)letcurrentthis.data.parsedObjfor(leti0;ikeys.length;i){constkeykeys[i]if(Array.isArray(current)){currentcurrent[parseInt(key)]}elseif(typeofcurrentobject){currentcurrent[key]}}constresulttypeofcurrentobject?JSON.stringify(current,null,2):String(current)this.setData({queryResult:result})}输入data.categories[0].tools[0].name直接拿到图片压缩。工具 3AA 分账 —— 最接地气的工具这个工具使用场景很简单朋友聚餐多人分摊费用。但就是这样一个看似不起眼的小工具却成了整个工具箱里使用频率最高、口碑传播最快的一个。为什么需要它聚餐结账时最尴尬的瞬间莫过于服务员拿着账单过来一桌人开始掏出手机各自计算。有人点了贵的菜、有人只喝了饮料、有人提前垫付了整桌费用——怎么算才公平用计算器一个个加既慢又容易出错用 Excel 又太小题大做。AA 分账工具就是为这个场景设计的。核心逻辑输入总金额、人数 → 自动计算每人金额支持有人先付了部分金额 → 算出谁该补给谁进阶场景差额结算除了最简单的总金额 ÷ 人数我还加了一个更实用的场景——有人垫付。比如小王先付了 500 元最后账单是 450 元那么小王应该拿回 50 元如果账单是 600 元其他人就要补给小王 150 元。工具会自动算出每个人该付多少、该补给谁避免谁先付谁吃亏的尴尬。交互设计金额输入支持小数点后两位自动过滤非法字符人数调整用步进器加减最少 2 人、最多 20 人结果展示每人金额大字居中显示下方列出谁该补给谁的明细一键复制把结算结果复制成文本直接发到群里省去手动打字的麻烦为什么它是拉新利器这个工具虽然逻辑简单但是拉新利器——每次聚餐大家都会用到用完还会分享给同桌的人。很多人第一次用是朋友转发的链接用完觉得方便就顺手收藏了整个工具箱进而发现里面还有 JSON 格式化、二维码生成这些开发工具。一个接地气的小工具成了整个工具箱的流量入口。五、架构设计亮点1. 数据驱动简历页面的内容全部抽到utils/resume-data.jsmodule.exports{name:瑞宸老师,title:前端开发工程师,city:重庆,// ... 所有简历内容}改内容只改这一个文件不动页面代码。这也是我在企业级项目中的惯用做法——数据和视图分离。2. 包体积控制整个项目只用了一个 npm 依赖weapp-qrcode没有引入任何 UI 框架或工具库。原因工具类小程序不需要复杂组件库每个工具的 UI 结构差异很大强行抽象反而增加耦合原生 API 已经够用wx.setClipboardData、wx.navigateTo等3. 安全考虑所有计算都在本地完成——没有网络请求不上传用户数据二维码生成纯 Canvas 渲染——内容不经过任何服务器MD5/SHA 哈希本地计算——敏感信息不会泄露这对于开发者工具来说是加分项——你不需要担心代码片段被传到某个服务器上。六、踩坑记录坑 1Canvas 2D API 兼容如前面所说wx.createCanvasContext已废弃必须用canvas.node.getContext(2d)。但很多第三方库还在用旧 API。我用的指令拦截方案完美解决了这个问题。坑 2rpx 适配微信小程序用rpx做响应式单位750rpx 屏幕宽度。但在 iPhone 上env(safe-area-inset-bottom)的处理要注意——底部操作栏必须保留安全距离.fixed-bar{padding-bottom:env(safe-area-inset-bottom);}坑 3小程序包大小限制单个包不能超过 2MB。虽然我的项目很小但如果后续加更多工具需要考虑分包加载subpackages。目前 9 个工具 图片资源还在 1MB 以内暂时不需要。七、从 0 到上线的完整流程1. 需求分析1 天列出最常用的工具按优先级排序。我选了上面 9 个作为第一版。2. 设计 UI2 天确定墨蓝 电光橙的配色方案CSS 变量设计令牌首页导航布局3. 开发工具5 天每个工具 0.5-1 天从简单到复杂时间戳转换最简单→ Base64 → JSON 格式化 → 二维码生成 → 图片压缩4. 测试与优化2 天微信开发者工具模拟器测试真机预览不同型号手机包体积检查5. 提交审核1-3 天小程序提交审核微信团队审核通过后发布。八、后续规划计划加入的工具颜色选择器 / 色值转换HEX ↔ RGB ↔ HSL正则表达式测试图片转 Base64Cron 表达式解析计划加的功能分享功能——每个工具页加一键转发按钮最近使用记录——快速回到上次用的工具搜索工具——工具多了以后按名字搜索九、总结做这个小程序的体会微信小程序做工具类应用天然合适——不用安装、不用注册、即用即走原生开发在简单场景下是最佳选择——不需要框架的过度抽象CSS 变量是设计系统的基石——所有颜色走变量改一处全局生效容错设计决定用户体验——JSON 格式化能处理不规范输入比严格报错好用 10 倍全部本地计算不上传任何数据。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。