拓冰建站拓冰建站
首页 / 资讯中心 / 正文

基于微信小程序与Java后端的家庭理财管理系统全解析

简介基于微信小程序构建的家庭理财管理系统毕业设计项目面向计算机相关专业学生、Java后端开发者以及需要快速搭建理财类小程序demo的人群。系统围绕家庭收支核心场景实现用户注册登录、工资管理、记账本管理、贷款管理、管理员后台等模块并以家庭为单位实时查看收支动态理财分析模块侧重自动分析与报表可视化贷款管理支持金额、还款日期、利率等台账记录和还款提醒后台管理员可删除普通用户、重置密码整体界面以蓝色为主基调理财分析与贷款模块采用绿色突出业务划分清晰。资源压缩包共4个文件包含2个zip源码包客户端与服务端、1个sql数据库脚本和1个txt说明文档压缩后约4.62MB部署门槛低。目前已有314人学习下载属于较受欢迎的小程序毕业设计选题。通过这套源码与配套文档读者可掌握微信小程序前端与Java服务端联调、MySQL表结构设计、后台权限管理及贷款提醒机制的完整实现适合直接作为毕业设计参考或二次扩展基础。1. 为什么家庭理财管理系统要选微信小程序而不是传统 App很多毕业设计选题还停留在“后台管理系统 PC 页面”的阶段用户必须坐在电脑前才能记账、看报表。这套基于微信小程序的家庭理财管理系统换了个思路把工资管理、记账本、贷款管理、理财分析全部搬到微信里Java 后端只负责数据和权限控制MySQL 存账前端不用安装 App扫码即用。对想用 java源码 快速出一条完整毕设路线的同学来说这个项目最大的参考价值在于家庭多成员共享同一套账本数据后端用家庭 ID 隔离成员同时保留管理员账号做用户治理并不是一个简单的“记账 CRUD”。打开 family_bank.zip 能看到 client.zip 和 server.zip分别对应小程序前端和后端工程jizhang.sql 是初始化脚本。我按从下到上的顺序拆解先表结构再后端接口再小程序页面最后落到贷款管理和理财分析这两组最容易在答辩时被追问的功能。这样你既能理解“家庭收支动态汇总”是怎么算出来的也能在演示时把每一步都说得清。2. 从 jizhang.sql 看家庭理财系统的表结构与数据初始化2.1 数据模型怎么划分才能支撑“家庭维度”家庭理财系统不能只围绕单用户设计。需求里明确说了“以家庭为单位动态实时反应家庭收支情况”所以最核心的不是 user 表而是 family 表和 bill 表。每个用户注册时必须选择一个家庭或新建家庭user 表通过 family_id 关联到 family 表工资记录和记账流水都挂在 user_id 上再由 user_id 关联到 family_id。查询家庭收支时不需要逐条跨表 join 用户信息直接按 family_id 过滤即可。jizhang.sql 里我建议按以下 6 张表来拆。实际工程中也可以把管理员合进 user 表通过 role 字段区分少一张表但逻辑会稍微绕一点。表名职责说明关键字段family家庭分组隔离不同家庭的数据id、family_name、create_timeuser普通用户与管理员标识id、family_id、username、password、rolewage工资流水记录每月收入明细id、user_id、month、base_salary、bonus、insurance、tax、actual_incomebill记账本流水收支两类id、user_id、type、amount、category、occur_date、remarkloan贷款账目id、user_id、principal、annual_rate、months、start_date、end_date、statuscategory消费分类辅助账单统计id、type、name这套表设计里最容易被忽略的是 category。很多毕设直接把分类写死在程序里导致理财分析只能按日期聚合不能按“餐饮、交通、教育”等维度聚合。把分类抽成单独一张表账单表只存 category_id后续分析就可以灵活做饼图和趋势图。2.2 导入 jizhang.sql 并验证初始数据拿到工程后第一步不是打开 IDEA而是先把数据库跑起来。项目里的 jizhang.sql 应该已经包含了建库、建表和初始化数据的语句。命令行导入方式如下mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS family_bank DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p family_bank jizhang.sql第一行创建数据库时指定 utf8mb4是为了让账单备注里的 emoji 和中文不乱码。第二行导入数据。导入后建议立刻执行一次验证SHOW TABLES; SELECT id, username, family_id, role FROM user; SELECT COUNT(*) FROM bill;正常情况下能看到 user 表里至少有一条管理员账号。如果设计里管理员是独立表则 role 字段可以不要。我一般会把管理员用户名初始化为 admin密码用 MD5 加密后写入避免直接展示明文密码。这个账号在 jizhang.sql 的 INSERT 语句里就能看到用一个 32 位的哈希字符串占位真实密码在项目文档里注明。2.3 为什么工资表不合并进记账本有一种偷懒做法是把工资也当成一条 bill 记录type 字段填“收入”。这样做记账本查询方便但理财分析会很痛苦工资汇总要计算“应发工资 - 五险一金 - 个税 实发工资”如果这些字段全塞在 bill 的 remark 里SQL 里就得用字符串截取既慢又不安全。独立 wage 表的好处是工资字段可以结构化后端直接用 BigDecimal 计算月底生成“实际收入”的报表时一次 group by 就能得到每个家庭成员的收入总和。记账本里则只用一条收入流水记录最终实发金额避免重复统计。这种“底层明细字段独立 业务统计结果冗余”的设计是毕设项目里比较稳妥的方案。3. Java 后端源码拆解登录、工资管理和后台用户治理3.1 Spring Boot 工程结构与通用返回体server.zip 解压后是一个典型的 Spring Boot MyBatis-Plus 工程。常见结构分为 controller、service、mapper、entity、config 五层。实体类对应数据库表Mapper 负责 SQLService 处理业务Controller 暴露 HTTP 接口。为了避免每个接口返回格式不统一建议先做一个统一返回体Data public class Result { private Integer code; private String msg; private Object data; public static Result success(Object data) { Result r new Result(); r.setCode(200); r.setMsg(success); r.setData(data); return r; } public static Result error(String msg) { Result r new Result(); r.setCode(500); r.setMsg(msg); return r; } }这个返回体虽然简单但它决定了小程序前端能否用一个统一的 request 方法处理响应。code 固定 200 表示成功401 会在第 4 章用于跳转登录页。参数说明code 字段不止是业务状态也建议与 HTTP 语义靠拢便于调试工具直接看出问题。3.2 登录注册接口密码加密与 Token 签发用户注册时密码不能明文入库。这里用 Spring 自带的 DigestUtils 做 MD5 加密。虽然 MD5 强度不如 BCrypt但作为毕设演示足够重点是把加密逻辑单独抽成一个工具类。登录接口代码如下RestController RequestMapping(/api/user) public class UserController { Autowired private UserService userService; PostMapping(/login) public Result login(RequestBody MapString, String body) { String username body.get(username); String password DigestUtils.md5DigestAsHex(body.get(password).getBytes()); User user userService.lambdaQuery() .eq(User::getUsername, username) .eq(User::getPassword, password) .one(); if (user null) { return Result.error(用户名或密码错误); } String token JwtUtil.createToken(user.getId(), user.getRole()); return Result.success(token); } }这里用到 MyBatis-Plus 的 lambdaQuery避免了手写 XML。逻辑说明先按 username 和 password 查用户查到就签发 JWT查不到统一返回“用户名或密码错误”不告诉调用方具体是哪一项错防止撞库。JwtUtil 是自封装工具把 userId 和 role 放进 token 的 payload后续接口通过拦截器解析 token 获取当前用户而不是每次请求都把 userId 当参数传。3.3 后台管理接口删除用户与重置密码需求里强调的是“管理员账户能删除普通用户和更改普通用户账号密码”。这部分在架构上和普通用户接口属于同一套服务但需要单独做权限控制。我用一个简单的 interceptor 校验 token 里的 role如果不是管理员则直接拒绝。接口设计如下接口路径功能请求参数/api/admin/user/delete删除普通用户id/api/admin/user/reset重置普通用户密码id、newPassword/api/admin/user/list查看普通用户列表page、size、keyword删除用户不是简单地 removeById因为用户下面还有工资、记账、贷款数据不清理干净会产生脏数据。我一般这样写PostMapping(/admin/user/delete) public Result deleteUser(RequestBody MapString, Object req) { Integer currentRole getCurrentUser().getRole(); if (currentRole ! 1) { return Result.error(无管理员权限); } Integer id (Integer) req.get(id); userService.removeById(id); billService.lambdaUpdate().eq(Bill::getUserId, id).remove(); wageService.lambdaUpdate().eq(Wage::getUserId, id).remove(); loanService.lambdaUpdate().eq(Loan::getUserId, id).remove(); return Result.success(); }说明先校验权限再删除 user 表中的记录随后级联删除 bill、wage、loan 三张表。如果贷款记录已经产生利息计算结果这里也要同步清理。这套逻辑最大的坑是漏删子表导致后续按家庭 ID 统计收支时出现空指针或金额异常。重置密码的逻辑类似唯一要注意的是前端传入的新密码需要再次 MD5 后再 update。3.4 工资管理的计算与入账流程工资管理模块在页面上看起来像一张普通表单实际核心计算在后端。字段至少要有 base_salary、bonus、insurance、tax。后端计算实际收入BigDecimal actual baseSalary.add(bonus).subtract(insurance).subtract(tax);然后把 actual 作为一条收入类型的 bill 记录插入记账本。这就是“工资管理”和“记账本管理”的联动点。如果不这样做理财分析里的总收入就只看得到工资记录看不到报销、礼金等其他收入统计口径会比较窄。4. 微信小程序前端与后端联动记账本与理财分析的数据链路4.1 封装 wx.request 统一管理 token 和错误状态client.zip 里的小程序目录包含 pages、utils、components。页面分为登录注册、首页、记账本、工资、理财分析、贷款、个人中心。每个页面都需要发请求所以必须把 wx.request 封装成公共模块。我在 utils/request.js 里通常这样写const request (url, method, data) { const token wx.getStorageSync(token); return new Promise((resolve, reject) { wx.request({ url: http://localhost:8080 url, method: method || GET, data: data || {}, header: { Content-Type: application/json, Authorization: token }, success(res) { if (res.statusCode 401 || res.data.code 401) { wx.removeStorageSync(token); wx.reLaunch({ url: /pages/login/login }); reject(res.data); } else if (res.data.code 200) { resolve(res.data.data); } else { wx.showToast({ title: res.data.msg, icon: none }); reject(res.data); } }, fail(err) { wx.showToast({ title: 网络错误, icon: none }); reject(err); } }); }); }; module.exports { request };说明几个关键参数baseURL 写成http://localhost:8080只适合微信开发者工具本地调试用手机预览时要改成电脑的局域网 IP否则真机会找不到后端。Authorization 头从本地存储里取 token后端拦截器通过它识别登录用户。wx.reLaunch 用于强制回到登录页防止停留在需要登录的页面上后续再发请求重复报 401。4.2 记账本页面如何做到增删改查记账本是所有页面里交互最多的包含表单提交、列表加载、滑动删除和分类筛选。列表页需要考虑分页加载。常见做法是在 onReachBottom 里触发下一页Page({ data: { list: [], page: 1, size: 10, hasMore: true, famId: 0 }, onShow() { this.setData({ page: 1, list: [] }); this.loadBills(); }, loadBills() { request(/api/bill/page?page${this.data.page}size${this.data.size}, GET) .then(data { const list this.data.list.concat(data.records); this.setData({ list, hasMore: data.current data.pages }); }); }, onReachBottom() { if (this.data.hasMore) { this.setData({ page: this.data.page 1 }); this.loadBills(); } } });这段代码体现的是“下拉刷新清空列表、触底加载下一页”模式。分页参数 page 从 1 开始size 决定每页条数。后端返回的对象里通常包含 records、current、pages 三个字段current 小于 pages 时说明还有数据。注意在 onShow 中刷新列表这样从添加账单页返回时首页数据也能同步更新。4.3 理财分析报表如何从多张表聚合而来理财分析模块直接决定项目答辩的亮点。首页收入支出总览、记账本分类统计、贷款剩余情况都要在一张页面上展示。这部分最难的是后端聚合逻辑因为数据来自 bill、wage、loan 三张表。我通常在后端提供一个/api/analyze/summary接口返回以下结构{ income: 15800.00, expense: 9630.00, balance: 6170.00, categoryExpense: [ { name: 餐饮, value: 3200 }, { name: 交通, value: 1200 } ], monthTrend: [ { month: 2025-01, income: 15000, expense: 9000 }, { month: 2025-02, income: 15800, expense: 9630 } ] }小程序的理财分析页面拿到数据后用 ECharts 组件画折线图和饼图。需要特别提醒的是不要在前端对后端返回的浮点数直接做加减法JavaScript 的浮点精度会导致金额显示成 6170.000000001应该在 Java 后端用 BigDecimal 计算后把结果格式化为字符串或保留两位小数再返回。这一章还涉及页面的跳转路径通常包括 pages/index、pages/bill/list、pages/bill/edit、pages/wage/list、pages/analysis/index、pages/loan/list。合理配置 tabBar 能让理财分析和首页不能同时做 tab如果需要切换就把分析页做成二级页面保证 tabBar 不超过 4 项。5. 贷款管理绿色模块利息计算、还款提醒与主题色切换5.1 贷款数据的表结构与月供计算贷款管理模块在需求里被单独提出来要求管理贷款金额、日期、还款日期、利率并且要提醒。我建议按“一笔贷款一条记录”的方式存储字段如下字段含义示例principal贷款本金100000annual_rate年利率4.9months还款月数36start_date放款日期2025-01-01end_date结束日期2027-12-31status贷款状态0 未还清 / 1 已还清月供计算通常是等额本息。前端提交贷款信息时后端返回每期应还金额小程序端也保留一份计算函数用于快速预览。核心公式如下function calcMonthPay(principal, annualRate, months) { const monthlyRate annualRate / 12 / 100; if (monthlyRate 0) { return (principal / months).toFixed(2); } const pow Math.pow(1 monthlyRate, months); const monthPay principal * monthlyRate * pow / (pow - 1); return monthPay.toFixed(2); }参数说明principal 是本金annualRate 是年利率百分数所以要先除以 100 再除以 12 得到月利率。pow 是复利系数。如果利率为 0直接用本金除以月数。这里最容易被问的是“为什么不是简单的本金除以月数加上利息”因为等额本息每个月归还的本金都在变化月供不变但本金比例递增、利息比例递减。5.2 还款提醒的状态设计与定时任务还款提醒不是靠微信消息推送而是用户在进入贷款页面或首页时后端返回“待还贷款”列表。实现方式是在 loan 表里增加一个 next_pay_date 字段每次查询时判断SELECT id, principal, annual_rate, months, status, CASE WHEN end_date NOW() THEN 2 WHEN status 0 THEN 1 ELSE 0 END AS loan_status FROM loan WHERE user_id #{userId}用一个数值字段区分三种状态0 表示已还清1 表示正常未还清2 表示逾期。小程序端根据 loan_status 显示绿色、黄色、红色标签。如果毕业设计想加入主动提醒可以在 Spring Boot 启动类上添加EnableScheduling然后用Scheduled(cron 0 0 8 * * ?)每天 8 点检查到期贷款并写入一条通知记录。这里不需要引入消息队列一个小型的家庭理财系统用定时任务已经足够。5.3 蓝色基调下如何单独让贷款模块变绿需求里明确“小程序基调为蓝色理财分析和贷款管理整成绿色”。小程序支持页面级配置文件app.json 中全局窗口背景色为蓝色贷款页面里单独覆盖{ navigationBarBackgroundColor: #07c160, navigationBarTextStyle: white, navigationBarTitleText: 贷款管理 }这样导航栏就是绿色但页面内部按钮仍需要绿色风格。我一般会在 app.wxss 里定义 CSS 变量让贷款相关页面引用page { --loan-primary: #07c160; --loan-bg: #f0f9eb; --main-color: #007aff; }.loan-card { background: var(--loan-bg); border-left: 4rpx solid var(--loan-primary); }这样做的意义在于全局的蓝色主题通过--main-color控制贷款页面只覆盖自己的变量以后要整体更换主题色时不需要改几十个页面文件。这也是答辩时可以主动展示的设计细节。6. 本地部署与加载页细节从 jizhang.sql 到微信小程序能跑起来6.1 启动顺序和常见环境问题部署顺序建议先导入 jizhang.sql再启动 Java 后端最后在微信开发者工具中导入 client.zip。后端启动前要确认 application.yml 里的数据库密码正确MySQL 版本最好在 8.0 以下或使用 mysql-connector-java 对应的 8.0 驱动。我遇到过最典型的问题是 MySQL 连接 URL 少了serverTimezoneAsia/Shanghai导致日期字段偏移 8 小时。启动后先用 curl 验证后端curl -X POST http://localhost:8080/api/user/login \ -H Content-Type: application/json \ -d {username:admin,password:admin123}响应里返回 code 200 和 token说明后端环境正常。然后在小程序工具中登录页面测试。如果真机连不上把 request.js 里的 localhost 改为电脑局域网 IP并在微信开发者工具中勾选“不校验合法域名”。6.2 如何修改刚进入的加载页面与顶部导航栏高度微信小程序启动时首先加载 app.json 中 pages 数组的第一项。毕业设计里默认可能是 pages/index/index如果想让它先进入 loading 页或登录页直接调整数组顺序即可{ pages: [ pages/loading/loading, pages/index/index, pages/login/login ] }loading 页面里写一个 setTimeout 跳转这样启动体验会比直接进入首页柔和很多。另一个高频修改点是自定义顶部导航栏。默认导航栏高度在 iPhone X 及以上机型会顶到状态栏导致页面标题整体偏低。改法是把想要自定义导航栏的页面单独配置{ navigationStyle: custom }然后在 onLoad 中获取胶囊按钮位置和状态栏高度const windowInfo wx.getWindowInfo(); const capsule wx.getMenuButtonBoundingClientRect(); this.setData({ statusBarHeight: windowInfo.statusBarHeight, navBarHeight: (capsule.top - windowInfo.statusBarHeight) * 2 capsule.height });这段代码中 statusBarHeight 是状态栏高度navBarHeight 是导航栏的总高度计算值。获取后把页面的 header 容器 padding-top 设置为 statusBarHeight 高度title 居中对齐到胶囊区间即可做到和微信原生导航栏一致的视觉效果。这个方法在贷款管理等绿色页面同样适用只需要把导航栏背景色和文字颜色从全局配置中剥离出来在 wxss 里分别处理。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门