当前位置: 首页 > news >正文

【个人记账理财助手】手动新增账单功能

手动新增账单功能

项目背景:这是一个个人消费分析和理财助手 APP,主要能力包括账单记录、分类统计、图表分析、AI 对话以及微信/支付宝账单导入。前面已经把首页账单列表和数据分析页接到了后端,这次补上一个很基础但使用频率很高的功能:手动新增账单。

一、为什么先做手动记账

一开始做这个项目的时候,我更关注“自动化”和“分析”这两个点,比如账单导入、图表汇总、AI 问答这些功能看起来更完整,也更像一个理财助手。

但真正把 APP 跑起来之后,会发现一个很实际的问题:不是所有消费都会稳定地从第三方账单导入进来。比如现金支出、临时转账、银行卡消费,或者用户只是想快速补一笔账,这些场景都需要一个手动入口。

所以这次选择先完成“手动新增账单”:

  • 首页中间的加号不再是空按钮,而是进入新增账单页;
  • 用户可以选择支出或收入;
  • 填写金额、交易对象、分类、支付方式、交易时间等信息;
  • 保存后写入后端数据库;
  • 返回首页后自动刷新本月汇总和账单列表。

这个功能不算大,但它决定了整个记账链路是不是闭环。

二、整体实现思路

这次改动分成前后端两部分。后端主要做一件事:提供新增账单接口。前端主要做三件事:新增表单页、首页加号跳转、保存成功后刷新首页数据。

首页点击加号

进入新增账单页

填写金额、交易对象、分类、时间

前端表单校验

POST /bills

后端创建 Bill 记录

返回首页并刷新汇总

我个人比较在意的一点是:这个页面不能只是“能提交”,还要尽量贴近日常记账的动作。用户打开页面时,默认就是“支出 + 餐饮 + 微信支付 + 当前时间”,这样大多数日常消费只需要填金额和商家就可以保存。

三、后端新增账单接口

后端原来已经有账单列表、月度汇总、删除、更新等接口,但缺少一个真正用于手动创建账单的接口。

新增的请求模型包含金额、交易对象、平台、分类、收支方向、交易时间、商品说明和备注:

classBillCreateRequest(BaseModel):amount:StrictStr counterparty:StrictStr platform_type:StrictStr transaction_type:StrictStr transaction_direction:StrictStr time:datetime product:str|None=Noneremark:str|None=None

这里金额用了字符串传递,主要是为了避免前端浮点数传输时出现精度问题。后端真正入库时再统一转成Decimal

接口路径设计为:

POST /bills

接口内部会从 token 中取当前用户 id,把请求参数组装成Bill,金额转成Decimal后写入数据库,最后返回统一的账单列表项结构。

bill=Bill(amount=Decimal(request.amount),counterparty=request.counterparty,product=request.product,platform_type=request.platform_type,transaction_type=request.transaction_type,transaction_direction=request.transaction_direction,time=request.time,remark=request.remark,user_id=user_id,)

这里有个小细节:新增账单一定要绑定当前登录用户,而不是让前端传user_id。这样可以避免用户伪造请求把账单写到其他人名下。

四、前端新增账单页面

前端新增了一个AddBillPage,页面结构没有做得太复杂,主要分成三块:

  • 账单类型:支出 / 收入;
  • 基础信息:金额、交易对象、分类、支付方式;
  • 补充信息:交易时间、商品说明、备注。

1. 支出和收入分类分开

刚开始我考虑过直接用一个分类列表,但后面发现这样体验不好。比如“工资”明显应该属于收入,“餐饮”明显应该属于支出,如果混在一起,后续做统计时也容易出现误选。

所以前端维护了两组分类:

final_expenseTypes=const["餐饮","交通","购物","居住","娱乐","医疗","学习","其他"];final_incomeTypes=const["工资","转账","奖金","退款","其他"];

切换“支出/收入”时,会自动把分类切到对应列表的第一个值:

_transactionType=direction=="收入"?_incomeTypes.first:_expenseTypes.first;

这个处理看起来很小,但可以减少很多无效数据。比如用户从支出切到收入后,分类还停留在“餐饮”,这类数据后面做统计就会很奇怪。

2. 表单校验放在前端先拦一层

金额和交易对象是必填项。金额校验主要判断两点:是否能转成数字,以及是否大于 0。

finalamount=double.tryParse(text);if(amount==null||amount<=0)return"请输入有效金额";

交易对象也必须填写。因为账单列表里最先展示的就是交易对象,如果这个字段为空,用户回到首页看到一堆空白记录会很难受。

当然,前端校验只是为了提升体验,后端也仍然要保留模型约束。

3. 时间选择

手动记账很常见的场景是“补记昨天的一笔账”,所以交易时间不能只用当前时间。

页面里用showDatePickershowTimePicker组合选择时间:

finaldate=awaitshowDatePicker(...);finaltime=awaitshowTimePicker(...);

最终传给后端的是 ISO 格式时间:

'time':time.toIso8601String()

这样后端用datetime接收会比较自然,后续做按月统计、按年筛选也方便。

五、首页加号接入

原来首页中间的 FAB 只是一个空方法:

onPressed:(){},

这次改成跳转新增账单页面:

finalcreated=awaitGet.to(()=>constAddBillPage());

保存成功时,新增页面会:

Get.back(result:true);

首页收到true之后做两件事:切回首页 tab,并调用HomeController.refresh()重新请求首页数据。这样用户保存完账单后,不需要手动下拉刷新,也不需要重启 APP,本月支出和账单列表会立刻更新。

六、联调过程中遇到的小问题

1. 前后端端口要对齐

这个项目后端默认跑在8080,Android 模拟器访问宿主机需要用:

http://10.0.2.2:8080

如果这里端口不一致,前端页面是能打开的,但保存账单会一直请求失败。这个问题不复杂,但调试时很容易误以为是 token 或接口参数的问题。

2. 保存后必须刷新首页

一开始只做了新增接口和页面跳转,但如果保存后首页不刷新,用户会觉得“是不是没保存成功”。所以保存成功后的刷新非常关键。这个地方不是单纯的页面体验问题,它也影响用户对数据可靠性的判断。

3. 支出和收入不能混到一起统计

之前处理过一个问题:工资被算进支出统计里。做手动记账时我也特别注意了这个点,新增账单必须明确带上transaction_direction

也就是说,“分类”解决的是这笔账属于餐饮、交通、工资还是转账;而“收支方向”解决的是它到底是支出还是收入。两个字段不能混用。

七、测试与验证

后端补了一个新增账单接口测试,主要验证:

  • POST /bills能正常创建账单;
  • 返回金额格式正确;
  • 交易对象、支付平台、分类、收支方向都能正确返回;
  • 数据确实写入数据库。

这次跑了相关测试:

uv run pytest tests/test_bill_api.py tests/test_analysis_api.py

结果:

23 passed

前端也跑了静态检查:

flutter analyze

目前剩下的是项目里原有的一些 info 级别提示,比如命名风格和部分旧 API 提示,没有新增错误。

最后还在 Android 模拟器里走了一遍真实流程:打开首页,点击中间加号,填写金额和交易对象,点击保存,返回首页后本月支出变化,列表顶部出现新账单。

这一步很重要,因为接口测试只能证明后端能用,模拟器验证才能证明用户真实路径是通的。

八、这次开发后的感受

手动新增账单这个功能看起来不像 AI 对话、图表分析那样“亮眼”,但它其实是记账 APP 里最基础的一环。

这次做完之后,我对这个项目的理解也更清楚了一点:一个理财助手不能只靠分析结果吸引用户,它首先要让用户愿意把数据记进去。数据入口越顺,后面的统计、图表、AI 问答才越有价值。

后面如果继续优化,我会优先考虑这几个方向:

  • 新增账单后支持编辑和删除的快捷入口;
  • 分类支持用户自定义;
  • 根据交易对象自动推荐分类;
  • 金额输入键盘做得更像记账软件,比如支持简单计算;
  • 首页加一个“最近常用商家”,减少重复输入。

这次功能的代码量不算小,但核心逻辑并不复杂。真正需要注意的是数据字段要清晰,尤其是金额、分类、收支方向、时间这几个字段。只要这些基础数据稳定,后面的消费分析才不会跑偏。

九、总结

这次完成的是个人消费分析 APP 的手动记账闭环:

  • 后端新增POST /bills接口;
  • 前端新增AddBillPage
  • 首页加号接入新增页面;
  • 保存成功后自动刷新首页数据;
  • 补充了后端接口测试;
  • 在 Android 模拟器里完成了真实流程验证。

从结果来看,这个功能让 APP 从“能展示账单”往“能主动记录账单”迈了一步。虽然只是一个基础功能,但它对后续的数据分析、图表统计和 AI 财务问答都有直接帮助。

http://www.rkmt.cn/news/1439582.html

相关文章:

  • 第1篇 | 政治思维生存逻辑解析
  • 无人机红外数据集 深度学习框架 无人机高空红外检测系统pyqt5界面 无人机高空红外数据集 无人机高空红外行人车辆检测数据集
  • 波普尔主义百年灾难清单:系统性尸检报告
  • 2026年最新厦门市金银首饰回收+金条金币+铂金K金 高价回收;实体老店回收黄金 多年口碑 交易放心;TOP5实力权威排行榜推荐+联系方式 - 亦辰小黄鸭
  • 2026年最新汕头市金银首饰回收+金条金币+铂金K金 高价回收;实体老店回收黄金 多年口碑 交易放心;TOP5实力权威排行榜推荐+联系方式 - 亦辰小黄鸭
  • 10. JavaArrayList 核心笔记
  • 第五章:年终
  • [分享]EssentialPIM安卓版(手机个人信息管理软件)
  • 告别静音!Windows 11系统声音保姆级配置指南(附完整音效清单与事件对照表)
  • 智慧火灾巡检-基于深度学习火灾烟雾识别系统,森林火灾识别系统。森林火灾检测 无人机森林火灾检测
  • VSCode配置QT环境
  • 华为eNSP静态路由实验教学
  • 航拍地面目标数据集1713张VOC+YOLO格式
  • Ubuntu 远程登录配置
  • 工厂设备预测性维护的必要性与实践案例
  • 别再死记硬背了!用Spring Boot实战案例,5分钟搞懂UML类图的6种关系
  • 告别无效刷屏!TrendRadar:最快30秒部署的开源热点助手,让你只看真正关心的新闻
  • 当AI能够创造AI时,人类该如何与其共舞?
  • 从保温杯到CPU散热:聊聊不良导体热导率测量的那些事儿
  • 从图形学老将到NeRF新贵:聊聊Instant-NGP里球谐函数的前世今生
  • 远程开发实战:在AutoDL云服务器上跑通COLMAP GUI并显示到本地VSCode(VNC+SSH隧道全攻略)
  • JDspyder:京东抢购成功率提升300%的自动化脚本技术解析
  • 别再死记硬背!用Python/Matlab模拟电化学暂态过程(附代码)
  • 22kW双向CLLC谐振DC-DC模块全套工程资料:含AD/Cadence双格式PCB、TI C2000 CCS源码、SiC器件应用指南与完整BOM
  • 天津除甲醛公司哪家好?2026年5月推荐生态美家口碑靠谱品牌对比 - 品牌推荐
  • 人类与AGI认知能力对比:从模式识别到创造性思维的深度分析
  • 从‘泵’的原理到实战:一个电容两个二极管,轻松玩转电荷泵升压与降压
  • 终极指南:如何快速免费将NCM文件转换为MP3/FLAC格式
  • 用Python模拟《信任的进化》博弈游戏:复读机策略为何总能赢?
  • Arm CoreLink NI-710AE NoC架构与安全隔离机制解析