前言:我想要一个什么样的工具?
作为一个有记账习惯但坚持不下来的开发者,我一直想要一个足够简单的资产管理工具。它不需要记录每一笔消费,只需要让我知道两件事:
- 我现在总共有多少钱
- 相比上个月是涨了还是跌了
找了一圈没有满意的,干脆自己动手写了一个。这篇文章记录我在技术选型、架构设计和开发过程中遇到的一些问题,希望能给想做类似小工具的开发者一些参考。
一、技术选型:为什么选择微信云开发
1.1 为什么不做独立App
- 开发成本:iOS和Android双端开发周期长
- 获客成本:用户需要下载安装,转化路径长
- 更新成本:发版审核周期不确定
1.2 微信小程序的优劣势
优势是用户即用即走、无需安装;劣势是包体积限制、部分API能力受限。权衡之后,小程序仍是工具类产品的最优解。
1.3 云开发 vs 自建后端
我最终选择了微信云开发这套方案,核心考量是:
| 维度 | 自建后端 | 微信云开发 |
|---|---|---|
| 服务器运维 | 需要自己管理 | 免运维 |
| 数据安全 | 需自行加固 | 平台级隔离,用户OpenID天然隔离 |
| 开发成本 | 前后端都要写 | 云函数+数据库,快速上手 |
| 扩缩容 | 需预估容量 | 按量付费,自动扩缩容 |
对于个人开发者来说,云开发让我可以把精力集中在业务逻辑上,而不是折腾服务器。
二、数据模型设计:抛弃流水账,采用“快照”模型
这是我认为最有价值的部分,也是这个工具的核心思路。
2.1 传统记账模型的问题
传统记账App的数据结构通常是:
// 流水账模型
{
transactionId: 'xxx',
time: '2024-10-31 12:30',
category: '餐饮',
amount: -58,
account: '招商银行卡'
}
这种模型需要用户高频记录,而且分类维度越多,用户负担越重。数据表明,90%的用户会在一个月内放弃。
2.2 资产快照模型的设计
我的方案是彻底放弃流水,只记录“快照”:
// 资产快照模型
{
snapshotId: 'xxx',
userId: 'openId',
date: '2024-10-31', // 每月只记录一次
accounts: [
{ name: '招商储蓄卡', amount: 50000 },
{ name: '余额宝', amount: 30000 },
{ name: '基金账户', amount: 20000 }
],
totalAssets: 100000,
createdAt: Date.now()
}
核心思路:与其每天记录怎么花钱,不如每月固定一天记录自己还剩多少钱。把高频、痛苦的记录,变成低频、有仪式感的复盘。
2.3 增长率的计算逻辑
基于快照数据,计算各种指标就变得非常简单:
// 云函数:计算增长率
exports.main = async (event) => {
const { snapshots } = event
// 按月排序
const sorted = snapshots.sort((a, b) => a.date - b.date)
// 月度增长率
const monthlyRates = []
for (let i = 1; i < sorted.length; i++) {
const prev = sorted[i-1].totalAssets
const curr = sorted[i].totalAssets
const rate = (curr - prev) / prev
monthlyRates.push({
month: sorted[i].date,
rate: (rate * 100).toFixed(2) + '%'
})
}
// 年度化收益率(简化版)
const first = sorted[0].totalAssets
const last = sorted[sorted.length-1].totalAssets
const months = sorted.length
const annualizedRate = Math.pow(last/first, 12/months) - 1
return {
monthlyRates,
annualizedRate: (annualizedRate * 100).toFixed(2) + '%'
}
}
三、数据可视化:基于 echarts-for-weixin 的优雅实现
资产走势图是用户感知价值最直观的模块。我选择了 echarts-for-weixin 这个成熟方案,它封装了 ECharts,能快速在小程序里画出各种专业图表。
3.1 为什么选择 echarts-for-weixin
对比了几个方案后,echarts-for-weixin 胜出:
| 方案 | 优点 | 缺点 |
|---|---|---|
| echarts-for-weixin | 功能强大,社区活跃,文档齐全 | 包体积稍大(约200KB) |
| wx-charts | 轻量 | 维护停滞,功能有限,无法满足复杂需求 |
| 自行绘制Canvas | 完全可控,体积最小 | 开发成本高,触摸交互难实现 |
考虑到资产走势图需要支持缩放、滑动查看历史数据,交互复杂度较高,直接使用成熟的 ECharts 组件能大幅降低开发成本。
3.2 集成与基础配置
集成方式很简单,从 GitHub 下载 echarts-for-weixin 组件,放到项目 components 目录下,然后在页面 json 中声明:
{
// ...
"usingComponents": {
// ...
"ec-canvas": "/components/ec-canvas/ec-canvas"
}
}
在 wxml 中使用:
<ec-canvas id="trendChart" canvas-id="trendChart" ec="{{ {lazyLoad: true} }}"></ec-canvas>
在 js 中初始化图表(以账户走势为例):
initAccountTrendChartComponent() {
const { accountTrendData } = this.data;
if (!accountTrendData || accountTrendData.length === 0) {
return;
}
const chart = this.selectComponent('#accountTrendChart');
if (chart) {
chart.init((canvas, width, height, dpr) => {
return this.initAccountTrendChart(canvas, width, height, dpr);
});
}
}
3.3 遇到的几个坑及解法
坑1:图表容器尺寸获取不到
- 现象:在页面加载时,
ec-canvas组件的宽高为0,导致图表渲染异常。 - 解决:在
onReady生命周期中初始化,或者使用wx.createSelectorQuery()获取容器尺寸后再初始化。
坑2:切换 tab 后图表不显示
- 现象:图表在隐藏的 tab 页面中,切换到该 tab 时图表区域空白。
- 解决:调用图表的
resize()方法,或者重新设置一次 option(echarts-for-weixin 会自动处理,但需要确保 canvas 上下文存在)。
坑3:数据更新后图表重绘闪烁
- 现象:频繁更新数据时,图表闪动,体验不好。
- 解决:使用
setOption的第二个参数设为false,表示不合并数据,直接覆盖,并配合防抖控制更新频率。
3.4 性能优化
echarts-for-weixin 本身已经做了 Canvas 渲染优化,但为了更流畅的体验,我做了两点优化:
- 按需加载:只在包含图表的页面加载 echarts 库,避免影响首页启动速度。
- 数据懒加载:初始只渲染空图表,等数据从云函数返回后再填充 series。
四、数据安全方案:基于微信云开发的隐私设计
作为资产管理工具,用户最关心的是数据安全。我的方案是:
4.1 数据存储隔离
所有数据存储在微信云数据库,每条记录都包含 _openid 字段,这是微信自动注入的用户标识。云数据库的权限设置为“仅创建者可读写”,天然实现了用户间的数据隔离。
4.2 无登录设计
用户无需注册,打开即用。用户的身份就是微信身份,数据跟着微信账号走,换设备也能无缝同步。
4.3 敏感信息处理
账户名称(如“招商银行储蓄卡”)由用户自定义,不会真的连接银行获取交易数据。所有数据都在用户可控范围内。
五、一些思考和总结
这个项目从构思到上线,断断续续花了两个月时间。最大的收获不是代码本身,而是对“工具”这件事的理解:
好的工具,不是功能越多越好,而是帮用户用最少的心智成本,解决最核心的问题。
对于个人资产管理,用户真正需要的不是知道每一笔钱花在哪,而是清晰地知道自己的资产在增长。这个认知,让我敢于放弃90%的“常规功能”,专注做好一件事。
如果你也在做类似的小工具,欢迎交流。我的经验是:技术选型上,微信云开发确实适合个人开发者快速验证想法;产品设计上,敢于做减法可能比堆功能更难。