news 2026/9/15 15:20:52

微信记账本小程序模板源码解析:配置、数据流与图表集成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
微信记账本小程序模板源码解析:配置、数据流与图表集成

简介:微信记账本小程序模板源码,面向小程序开发者与想快速搭建记账应用的学员,可帮助理解微信小程序项目结构、组件交互和记账功能的实现思路,也可作为课程设计或个人应用的起步模板。压缩包共39个文件、46KB,包含9个json配置、9个js逻辑、8个wxss样式、7个wxml结构、5个png图标和1个md说明文档;json控制项目与页面配置,js处理业务和数据逻辑,wxss/wxml搭建界面,png提供图标,md书写说明,便于对照学习和二次开发,体系完整。已有514人学习下载。源码内置账目录入、分类统计、数据分析等核心模块,并封装了wxcharts.js图表工具,便于练习页面渲染与数据绑定;同时项目配置与公共工具划分清晰,适合初学者对照阅读代码,也方便开发者在此基础上扩展预算管理、账单导出、多账本等个性化功能,或替换接口快速接入实际业务。

1. 微信记账本小程序模板源码先看什么

拿到以 zip 形式分发的微信记账本模板源码,别急着解压右键,先读一遍文件列表比打开代码更有用。这个包里同时出现 pages、common、settings、app.json、project.config.json、utils/wxcharts.js 和 util.js,意味着它是一套完整的小程序工程,不是只有几个页面的静态模板。它解决的问题很直接:让开发者拿到手就能看到账目录入、数据存储、统计图表这条完整链路,适合做课设、新手上手学习,或者当作项目原型二次开发。下面按启动配置、数据流、图表库和排错四个角度拆一遍,重点讲清楚哪些文件在启动时被加载,哪些坑会让模板跑不起来。

2. 从app.json到project.config.json的小程序骨架解析

2.1 app.json里的页面注册与窗口配置

小程序启动时会先读取 app.json,它同时承担路由表、窗口外观和 TabBar 注册三项职责。记账本这类工具型应用一般会让首页、流水页、设置页构成三个主页面,解压后打开 app.json,首先看 pages 数组的第一项,那就是用户打开小程序后看到的第一个页面。如果首页缺失或路径写错,开发者工具会直接报 module not found,并且白屏。

下面是一份常见的记账本模板 app.json 配置:

{ "pages": [ "pages/index/index", "pages/handbook/index", "pages/settings/index" ], "window": { "navigationBarBackgroundColor": "#2c3e50", "navigationBarTitleText": "微信记账本", "navigationBarTextStyle": "white", "backgroundColor": "#f5f5f5" }, "style": "v2", "sitemapLocation": "sitemap.json" }

这段配置里最重要的一项是 pages 数组的顺序,它不仅是路由注册表,也是加载顺序的依据。当模板里出现 handbook 这样的非英文命名目录,多半是从某个课设项目或商城模板抄过来改的,路径大小写必须和文件夹完全一致。window 中的 navigationBarTitleText 会直接显示在顶部导航栏,如果不需要标题可以留空字符串,但不能删除这个字段。

这里的核心参数可以按下表理解:

字段作用记账本模板里的常见设定
navigationBarBackgroundColor顶部导航栏背景色深色系,比如 #2c3e50
navigationBarTitleText导航栏标题文案微信记账本
navigationBarTextStyle导航栏文字颜色只能是 white 或 black
backgroundColor下拉刷新时露出的窗口底色浅灰 #f5f5f5
style是否启用新版组件样式v2 表示开启微信新版基础组件外观

需要特别注意的是,navigationBarTextStyle 只接受 white 和 black 两个值,写其他颜色不会生效且不报错。很多模板会把导航栏背景色改成白底,却忘了把文字颜色从 white 改成 black,结果标题看不见。这是从模板改成正式项目时最常撞上的第一个屏。

2.2 project.config.json里的appid与urlCheck

project.config.json 是开发者工具识别项目身份的文件,里面藏着两个关键配置:appid 和 urlCheck。用游客模式打开项目时 appid 会显示 touristappid,这时 wx.request 只能请求本地调试地址,想要连接真实后端,必须替换成自己的 AppID。

{ "appid": "touristappid", "compileType": "miniprogram", "libVersion": "2.33.0", "setting": { "urlCheck": false, "es6": true, "enhance": true, "postcss": true, "minified": true } }

这里的 setting 里,urlCheck 设为 false 可以让本地开发绕过合法域名校验。模板源码包里往往默认 false,方便你打开就能调试,但提审前必须改成 true 并在小程序管理后台配置 request 合法域名,否则正式版里所有网络请求都会失败。libVersion 指定基础库版本,如果模板用的 API 比较新,比如 Canvas 2D,需要将 libVersion 调到 2.9.0 以上,否则真机预览时会出现 canvas 相关的 undefined 报错。

另一个容易被忽略的是 compileType,它固定为 miniprogram,表示这是一个普通小程序项目,不是插件或小游戏。如果从网上下载的模板里这个字段被改成 game,开发者工具会直接打不开,界面提示项目类型不匹配,解决方法是先手动改成 miniprogram 再导入。

2.3 sitemap.json和app.wxss的全局影响

sitemap.json 控制小程序页面是否允许被微信索引。模板里的 sitemap.json 通常是:

{ "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html", "rules": [{ "action": "allow", "page": "*" }] }

记账类应用并不需要被搜索索引,比较好的做法是把 action 改为 disallow,避免隐私页面出现在微信搜索里。注意 sitemap 设置不会影响用户直接打开小程序,也不影响开发者工具编译。

app.wxss 是全局样式表,作用于所有页面。模板里它一般只放 page 级背景色、默认字体大小、flex 公共类。如果你把每个页面自己的 wxss 写在 app.wxss 里,团队协作时很容易出现样式覆盖链失控。正确做法是只在 app.wxss 里放全局变量和 reset,页面私有样式留在各个页面目录下的 wxss 文件里。小程序里样式单位是 rpx,750rpx 等于屏幕宽度,设计稿用 375px 时 1px 对应 2rpx,这是模板里大量出现 32rpx、24rpx 这类数值的原因。

3. 记账核心流程:账目录入、本地存储与util.js格式化

3.1 记账页的wxml数据绑定与事件流

pages/handbook/index 这个目录名直译是手册,但在记账本模板里它就是手动记账页。这个页面的 wxml 结构一般是输入框、分类选择栏、保存按钮三块。数据绑定方式用的是小程序基础的{{}}插值,配合 input 的 bindinput 事件实时更新 data 里的字段。

<view class="form"> <input type="digit" placeholder="0.00" value="{{amount}}" bindinput="onAmountInput"/> <picker range="{{categories}}" value="{{categoryIndex}}" bindchange="onCategoryChange"> <view>{{categories[categoryIndex] || '选择分类'}}</view> </picker> <textarea placeholder="备注" value="{{note}}" bindinput="onNoteInput"></textarea> <button type="primary" bindtap="saveRecord">记一笔</button> </view>

这里 input 的 type 用了 digit,目的是让数字键盘弹出,但 digit 类型在 Android 和 iOS 上的表现并不一致,iOS 会出现无法输入小数点的问题。更稳妥的做法是 type="text" 配合输入后的正则校验,或者在 bindinput 里自己过滤非法字符。picker 组件是模板分类选择的常规方案,bindchange 事件返回的是选中项的索引,不是分类名称,拿到索引后再从 categories 数组里取值。

3.2 数据写入与storage结构设计

记账动作最终落到保存按钮,常见做法是把记录 push 到现有数组,再整体写回本地 storage。这里需要注意小程序 storage 的 key 是全局共享的,同一个 key 在不同页面都能读写,所以需要约定一个固定名字,比如 records。

const util = require('../../utils/util.js'); Page({ data: { amount: '', category: '餐饮', categories: ['餐饮', '交通', '购物', '生活', '娱乐'], categoryIndex: 0, note: '' }, saveRecord() { let amount = parseFloat(this.data.amount); if (!amount || amount <= 0) { wx.showToast({ title: '金额不对', icon: 'none' }); return; } let records = wx.getStorageSync('records') || []; records.unshift({ id: Date.now(), amount: amount, category: this.data.category, note: this.data.note, time: util.formatTime(new Date()) }); wx.setStorageSync('records', records); wx.showToast({ title: '已记一笔', icon: 'success' }); } })

这段代码里有几个细节值得展开。第一,records.unshift 而不是 push,因为新记录在列表中必须显示在最上面,unshift 把元素插入数组头部。第二,用 Date.now() 作为 id 在单机场景下够用,但如果后续要同步到云端,高并发写会产生相同 id,最好改成Date.now().toString(36) + Math.random().toString(16).slice(-4)。第三,amount 必须用 parseFloat 转换,因为 input 拿到的永远是字符串,直接存进去会导致统计时计算错误。

字段设计可以对齐这个结构:

字段类型说明
idstring唯一标识,用于删除和编辑
amountnumber金额,以分为单位会更好
categorystring分类名称,不要存索引
notestring备注,可为空
timestring格式化后的时间,用于分组

真机调试过账本类项目的人都会建议金额以“分”为整数存储,避免浮点误差。模板里如果直接存了浮点数,统计页做环比时可能会出现 0.30000000000000004 这种结果。稳妥方案是 save 时把 parseFloat 的结果乘 100 再取整,展示时再除以 100。

3.3 util.js与时间分组逻辑

utils/util.js 在模板里承担时间格式化功能,也是统计页按日、月、周分组的依据。一个合格的 formatTime 函数至少要有补零逻辑,否则横轴标签会显示 2025-3-5 而不是 2025-03-05,视觉上很不整齐。

function formatTime(date) { if (!date) date = new Date(); const year = date.getFullYear(); const month = date.getMonth() + 1; const day = date.getDate(); const hour = date.getHours(); const minute = date.getMinutes(); return [year, month, day].map(formatNumber).join('-') + ' ' + [hour, minute].map(formatNumber).join(':'); } function formatNumber(n) { n = n.toString(); return n[1] ? n : '0' + n; } function getMonthKey(date) { const d = date ? new Date(date) : new Date(); return d.getFullYear() + '-' + (d.getMonth() + 1 < 10 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1); } module.exports = { formatTime, getMonthKey };

这里单独封装 getMonthKey 的目的是为了让统计页做月份分组时有一个稳定的 key,直接拿 formatTime 的结果做月份分组会把日期也带进去。注意 getMonthKey 内部用new Date(date)重新构造了一次,因为外部传入的时间字符串如果是 'YYYY-MM-DD' 格式,在 iOS 上有兼容问题,直接 new Date('2025-03-05') 返回 Invalid Date,需要替换成 new Date('2025/03/05')。如果看到模板里时间显示 NaN,第一时间查这里。

3.4 onShow刷新而不是onLoad

这是一个很典型的刷新时机问题。index 首页从记账页保存返回后,需要立刻看到最新流水,如果统计数据是在 onLoad 里读取 storage,返回时 onLoad 不会再次触发,列表就停留在旧数据。正确的做法是把读取 storage 的逻辑放在 onShow 里,因为每次页面出现在前台时 onShow 一定会执行。

onShow() { this.setData({ records: wx.getStorageSync('records') || [] }); this.updateSummary(); }

这样做成本低且效果直接,比用事件通道或全局变量省事。但在首页有图表时,onShow 里频繁 setData 会触发整个页面重绘,需要结合下一页说的图表实例更新方式做节流,而不是每次无脑 new 图表。

4. wxcharts.js在统计页里的图表集成与参数陷阱

4.1 为什么模板还在用wxcharts.js

wxcharts.js 是微信小程序早期常用的 canvas 图表库,因为界面简洁、依赖少,被大量开源项目封装进模板。它的实现基于旧版 canvas 1.0 接口,通过 wx.createContext 获取绘图上下文,而不是现在推荐的 Canvas 2D。模板源码里保留 wxcharts.js,说明这个项目的基础库版本可能停留在 2.9 之前,或者模板作者为了兼容低成本复制。

用它的理由是开箱即用,不必为了一张折线图引入整个 echarts 适配层;代价是后期如果要加交互式 tooltip 或手势缩放,基本做不到,只能自己画。因此这个库适合做静态统计展示,不适合做复杂图表。

4.2 初始化折线图与canvas尺寸匹配

统计页里最常见的图表是月度支出趋势,初始化代码长这样:

const wxCharts = require('../../utils/wxcharts.js'); Page({ data: {}, onReady() { this.initTrendChart(); }, initTrendChart() { let months = ['1月', '2月', '3月']; let values = [320, 580, 460]; this.trendChart = new wxCharts({ canvasId: 'trendChart', type: 'line', categories: months, series: [{ name: '支出', data: values }], width: 320, height: 200, animation: true, yAxis: { format: function (val) { return val.toFixed(0); } } }); } })

对应 wxml 里需要有一个 canvas 节点:

<canvas canvas-id="trendChart" id="trendChart" style="width:320px;height:200px;"/>

这里最容易踩的是尺寸不一致。wxCharts 实例里 width 和 height 的单位是 px,不是 rpx。如果 canvas 节点样式写的是 320rpx,而实例里宽高写的是 320,实际绘制区域和节点区域对不上,图表会被裁切或拉伸。另一个坑是 canvas-id 和 id 不是一回事,wxCharts 用的是 canvas-id,改成纯数字在旧版本基础库上会找不到画布,建议统一使用带字母的 id。

yAxis.format 函数接收一个数值,返回用于坐标轴展示的文本。在这段里对数值调用 toFixed(0),是为了不显示小数点。如果你发现图表 y 轴出现很多小数,检查这里是否忘记格式化。

参数表如下:

参数类型示例作用
canvasIdstringtrendChart对应 wxml 的 canvas-id
typestringline / pie / column图表类型
categoriesarray['1月','2月','3月']横轴分类
seriesarray[{name:'支出', data:[...]}]数据系列
width / heightnumber320 / 200绘制区域 px 尺寸
animationbooleantrue是否开启动画
yAxis.formatfunctionval => val.toFixed(0)y 轴数值格式化

4.3 动态更新与多实例销毁

从首页 onShow 里更新图表时,如果直接再次 new wxCharts,旧画布不会自动清理,会出现原图和重影叠加。正确做法是把首次创建实例保存到 this 上,后续只调用 updateData。

this.trendChart.updateData({ categories: ['4月', '5月', '6月'], series: [{ name: '支出', data: [210, 330, 540] }] });

updateData 会在原实例上重绘,不会创建新的 canvas 层。多次调用不会累积内存,但代价是动画效果会被截断。如果你需要完全无动画更新,可以在更新前设置animation: false

还有一点,统计页如果同时包含柱状图和饼图,建议把整个 wxml 包在 v-if 里按需渲染,而不是放着两个隐藏 canvas。wxcharts 在隐藏节点上绘图会得到宽高为 0 的画布,控制台不报错但图像空白,排查起来很费时间。

4.4 与uniapp微信小程序项目的差异

如果你之前接触过 uniapp 微信小程序项目,会注意到 uni-app 里没有直接 require('../../utils/wxcharts.js') 的做法。uni-app 的 renderjs 和 canvas 封装不同,wxcharts 的 createContext 调用方式无法被 uni-app 编译层完全识别,强行引入会导致真机预览没有图表。uni-app 项目一般用 ucharts 或 echarts 的 uni 版本,它们封装好了 renderjs 通信。因此这份源码里的 wxcharts.js 只能在原生微信小程序项目里运行,不要花时间尝试移植到 uniapp 工程。

5. 二次开发排错:加载页、模板字符串与canvas验证

5.1 修改刚进入的加载页面

模板源码包的 pages 目录里如果没有单独的 loading 页面,那么 app.json 中 pages 数组第一位就是用户看到的加载页。很多模板会把一个全屏品牌页放在第一位,然后通过 setTimeout 跳转到首页。这个设计在新版微信审核里越来越不受欢迎,尤其是跳转延迟超过 3 秒会被认为影响体验。最干净的做法是直接把业务首页放在 pages 数组第一位,把品牌信息融入首页头部。

如果你的模板确实带了 landing 页面,并且你想把它改掉,只需要调整 app.json 的 pages 顺序即可。注意不是删除 landing 目录,因为有的模板会在 app.js 里写死跳转逻辑,删掉文件会导致 app.js 抛异常。先搜索一下 app.js 里有没有 wx.redirectTo 或 wx.switchTab 再动手。

5.2 模板字符串与wxml模板语言的边界

JavaScript 里的模板字符串是反引号,WXML 里的数据绑定是双大括号,两者很容易混。在 WXML 中你不可以用模板字符串动态拼接 class 名,比如 class="{{'item-' + index}}",虽然这种写法能跑,但维护起来很糟糕。WXML 本身不支持复杂表达式,比较靠谱的做法是在 js 里预先算好,把结果赋值给 data 中的一个数组。

this.setData({ items: rawItems.map((item, index) => { item.className = index === 0 ? 'item-first' : 'item-normal'; return item; }) });

这样 WXML 里只需要写 class="{{item.className}}",页面结构更干净,也便于后续调整业务逻辑。

5.3 用三个步骤定位图表不显示

图表不显示是统计页最常见的故障,三步就能定位。第一,在当前页面的 onReady 里加一行 console.log,确认 wxCharts 实例是否成功创建,如果打印出对象但画布空白,看 canvas 节点是否有固定宽高,display:none 或父节点隐藏都会导致画布宽度为 0。第二,在 console 面板手动执行wx.getStorageSync('records'),确认数据格式是数组,且每个元素包含 amount 和 time 字段,如果数据是空数组,图表当然没有点。第三,检查基础库版本,在开发者工具右上角详情里看调试基础库是否低于 2.0,wxcharts 对旧版基础库兼容性更好,新版反而可能出现接口废弃警告。

如果还不行,就在 initTrendChart 里强制设置一个 yAxis.min 和 yAxis.max,比如 0 和 1000,排除坐标轴自动计算异常导致绘制范围异常的问题。一个能显示的折线图,至少要在控制台看到 canvas 节点宽度大于 0,并且 series[0].data 长度与 categories 数量一致。这两点满足后,模板里的记账图表基本都能正常渲染。

本文还有配套的精品资源,点击获取

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

新手入门必看:怎么做网页链接图片不踩坑?

新手入门必看:怎么做网页链接图片不踩坑? 昨晚刚把客户站发版,凌晨两点手机突然疯狂震动,微信弹出警报:“您的网站被检测到挂马,已强制拦截。”这种惊魂时刻,做网站的谁没经历过?很多新手入门时觉得只要代码写对就行,却忽略了最基础的“网页链接图片”处理,结果成了黑客的提款机。其实,图片链接里的一个…

作者头像 李华
网站建设 2026/9/15 15:19:16

非相称分数阶系统Lyapunov指数计算的Matlab实现

简介&#xff1a;面向分数阶系统与混沌动力学研究者的Matlab工具包&#xff0c;专注非相称分数阶自治连续时间系统的李雅普诺夫指数计算。代码基于Caputo导数建模&#xff0c;提供主函数与辅助函数&#xff0c;覆盖系统模型定义、分数阶微分方程数值求解到李雅普诺夫指数提取的…

作者头像 李华
网站建设 2026/9/15 15:18:43

欧洲一氧化碳报警器市场准入与认证要点解析

1. 欧洲一氧化碳报警器市场准入核心要点解析作为深耕安防产品出口领域十余年的从业者&#xff0c;今天想系统梳理下欧洲市场一氧化碳报警器的准入要求。这个看似简单的产品&#xff0c;在实际认证过程中藏着不少"暗礁"&#xff0c;我们团队曾因忽略某个细节导致整批货…

作者头像 李华
网站建设 2026/9/15 15:17:59

安卓饮食推荐Demo:从CSV清洗到百度API识别的数据驱动设计

简介&#xff1a;这是一份面向安卓开发学习者和毕业设计选题的智能饮食推荐App Demo源码&#xff0c;核心围绕“数据分析图像识别”实现个性化饮食管理。项目不仅覆盖用户健康档案、菜品卡路里/蛋白质/脂肪数据&#xff0c;还针对九体体质与减脂、增肌、塑形等目标联动推荐菜谱…

作者头像 李华