1. 项目背景与核心价值
去年我开始认真记账后,发现市面上大部分记账工具都存在两个痛点:要么功能太简单无法满足个性化需求,要么数据隐私让人担忧。作为一个全栈开发者,我决定自己动手开发一套完整的个人记账系统,包含网页端和微信小程序双平台。
这套系统最核心的价值在于:
- 完全掌控数据所有权(所有数据存储在个人服务器)
- 支持高度自定义的记账模板
- 实现跨平台数据同步
- 提供可视化数据分析功能
2. 技术架构设计
2.1 整体技术栈选型
经过对比主流方案,最终确定的技术组合:
前端:Vue3 + Vant(小程序端用Uniapp跨端方案) 后端:Node.js + Koa2 数据库:MySQL + Redis缓存 部署:Docker + Nginx选择这套方案主要考虑:
- 开发效率:Vue和Uniapp生态完善,组件丰富
- 维护成本:JS全栈技术统一,团队协作方便
- 性能需求:记账系统并发要求不高,MySQL完全够用
- 扩展性:Docker化部署方便后续扩容
2.2 数据库设计要点
核心表结构设计(简化版):
CREATE TABLE `accounts` ( `id` int NOT NULL AUTO_INCREMENT, `user_id` int NOT NULL COMMENT '用户ID', `amount` decimal(10,2) NOT NULL COMMENT '金额', `type` tinyint NOT NULL COMMENT '1收入 2支出', `category` varchar(20) NOT NULL COMMENT '分类', `remark` varchar(255) DEFAULT NULL COMMENT '备注', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;特别要注意的细节:
- 金额使用decimal而非float,避免精度丢失
- 建立复合索引(user_id, create_time)提升查询效率
- 添加字段版本号方便后续扩展
3. 核心功能实现
3.1 多端同步方案
采用增量同步策略解决多端数据一致性问题:
- 客户端记录本地最后同步时间戳
- 请求时携带时间戳获取增量数据
- 服务端使用Redis存储同步状态
- 冲突处理采用"最后修改优先"原则
关键代码示例(Node.js):
router.post('/sync', async (ctx) => { const { lastSync, clientData } = ctx.request.body; // 获取服务端增量数据 const serverChanges = await getChangesSince(lastSync); // 合并冲突 const mergedData = mergeChanges(clientData, serverChanges); // 返回最终结果 ctx.body = { changes: mergedData, newSyncTime: Date.now() }; });3.2 数据可视化实现
使用ECharts实现消费趋势分析:
- 按日/周/月聚合消费数据
- 动态生成环形图(分类占比)和折线图(趋势变化)
- 添加时间范围选择器
- 实现图表数据缓存(Redis 24小时过期)
性能优化技巧:
- 预生成常用时间段的统计结果
- 使用Web Worker处理大数据量计算
- 实现懒加载图表组件
4. 开发踩坑实录
4.1 微信小程序兼容性问题
遇到的典型问题及解决方案:
日期格式差异:iOS和Android表现不同
- 统一使用YYYY-MM-DD格式
- 引入day.js处理日期
登录态维护:
// 检查session是否过期 function checkSession() { return new Promise((resolve) => { wx.checkSession({ success: () => resolve(true), fail: () => resolve(false) }); }); }图片上传限制:
- 压缩图片到1MB以内
- 使用云存储CDN加速
4.2 安全防护措施
必须实现的几个安全防护:
- 接口防刷:令牌桶限流(100次/分钟)
- SQL注入防护:使用ORM或参数化查询
- XSS防护:前端DOMPurify过滤
- 敏感操作:短信二次验证
Nginx配置示例:
location /api/ { limit_req zone=api burst=20 nodelay; proxy_pass http://backend; }5. 部署与运维方案
5.1 Docker化部署
docker-compose.yml关键配置:
version: '3' services: db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} volumes: - ./mysql-data:/var/lib/mysql app: build: . ports: - "3000:3000" depends_on: - db environment: NODE_ENV: production5.2 监控与备份
必备的运维措施:
- 使用PM2守护进程
- 配置日志轮转(logrotate)
- 每日自动数据库备份(mysqldump + 七牛云存储)
- 基础监控(CPU/内存/磁盘报警)
备份脚本示例:
#!/bin/bash DATE=$(date +%Y%m%d) mysqldump -u root -p${DB_PASS} accounting > /backups/accounting_${DATE}.sql rclone copy /backups qiniu:backups6. 扩展优化方向
经过三个月实际使用后,发现还可以优化:
- OCR识别:对接支付宝/微信账单自动导入
- 多账本支持:区分个人/家庭/旅行等场景
- 预算功能:设置月度消费预警
- API开放:对接家庭NAS自动备份
实现OCR的简要思路:
- 使用Tesseract.js进行文字识别
- 设计正则表达式匹配金额和分类
- 人工确认后存入数据库
这个项目给我的最大启示是:个人项目要控制好功能边界,先实现核心功能再迭代扩展。记账系统的核心就是准确记录和清晰展示,花里胡哨的功能反而会影响使用体验。