资讯动态

养老院系统技术选型:Java+小程序+MySQL实战指南

发布时间:2026/10/26 8:08:32 来源:尧图企业网站定制
简介本资源是一套面向计算机专业本科生的微信小程序养老院管理系统毕业设计源码聚焦老龄化社会服务场景为学生提供可直接部署、二次开发与答辩演示的完整解决方案。资源包含1359个文件涵盖244个Vue页面组件、164个JS逻辑脚本、121个Java后端类、149个JSON配置及数据库SQL文件等全面支撑小程序前端、Spring Boot后端与MySQL 5.7数据层协同运行32MB压缩包内含eclipse/IDEA工程、Tomcat7部署配置、Navicat建库脚本及详细表结构文档.docx和项目说明.zip另有.bat一键构建/运行脚本与多格式图标资源显著降低环境搭建门槛。目前已有87人学习下载适合课程设计、毕设选题与Java小程序全栈技术实践者快速掌握前后端联调、数据库设计与微信生态集成要点。1. 养老院系统为什么非得用「Java 小程序 MySQL」这套组合——不是为了炫技是为交付时少改三遍接口、少填五张验收表你手头这份标着「【微信小程序毕业设计】养老院系统源码java小程序mysqlLW.zip」的压缩包表面看是个学生作业实则藏着一套被养老机构真实验证过的最小可行技术栈后端用 JavaSpring Boot 主流框架前端用原生微信小程序非 uni-app数据库用 MySQL5.7 或 8.0 均可配套文档含开题报告、需求分析、系统设计、测试用例、答辩PPT——也就是标题里那个「LW」论文/论文字母缩写。它解决的不是「能不能跑起来」而是「能不能过答辩、能不能现场演示、能不能让养老院管理员愿意点开用」。比如家属端小程序要实时看到老人今日服药记录后台 Java 接口必须支持高并发查询哪怕只有 20 个家属同时刷护工端扫码登记巡房MySQL 表结构得预留扩展字段如「异常描述 TEXT」否则后期加个跌倒拍照功能就得重构整张表而「微信小程序顶部导航栏高度」这种细节直接决定老人是否能看清「紧急呼叫」按钮——我们测过iOS 和安卓下 navigationBarHeight 实际渲染差 4px不处理就会把按钮压进安全区。这套组合没用 Node.js 或 Python是因为 Java 的 JPA/Hibernate MyBatis-Plus 对复杂业务逻辑如排班冲突校验、健康数据趋势计算更稳没选 SQLite 或云开发是因为养老院本地服务器部署 MySQL 是硬性要求数据不出院、审计留痕小程序不用跨端框架是为避开「uni-app 在 iOS 微信里真机调试卡顿」这个玄学坑。适合两类人应届生赶毕设 deadline或小型养老机构想快速上线轻量管理系统——它不追求百万级并发但求每一步操作都有日志、每次数据变更可追溯、每个页面加载不超过 1.2 秒。2. 搭建环境从解压到首页渲染只用 6 分钟完成本地可运行闭环拿到.zip后别急着导入 IDE。先确认三个核心组件版本是否匹配——这是后续所有翻车的起点。本项目常见依赖组合是JDK 1.8非 11、MySQL 5.7.32非 8.0.33、微信开发者工具 Stable 1.06.2309140非 Nightly 版。新版 JDK 会报Unsupported class file major version 61MySQL 8.0 默认 strict mode 会让INSERT INTO user VALUES (null, 张三)直接报错因id为自增但未显式设NULL而开发者工具 Nightly 版对wx.getPhoneNumberAPI 的回调时机有兼容问题。下面分三步走2.1 后端 Java 工程Spring Boot 2.3.x 启动关键配置解压后进入server/目录或backend/用 IntelliJ IDEA 打开pom.xml。重点检查三处parent标签内spring-boot-starter-parent版本是否为2.3.12.RELEASE本项目稳定基线properties中java.version是否为1.8application.yml里数据库连接配置需手动改spring: datasource: url: jdbc:mysql://localhost:3306/elderly_care?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseSSLfalse username: root password: your_mysql_password # ← 这里必须填你本地 MySQL 的密码 driver-class-name: com.mysql.cj.jdbc.Driver提示serverTimezoneAsia/Shanghai必须加否则 Java 读取 MySQL 时间字段会慢 8 小时allowPublicKeyRetrievaltrue是 MySQL 8.0 连接必需参数但本项目若用 5.7 可删掉。启动前右键ElderlyCareApplication.java→ Run观察控制台输出✅ 出现Started ElderlyCareApplication in X.X seconds且无Failed to configure a DataSource报错❌ 若报Access denied for user rootlocalhost说明 MySQL 密码不对或用户权限未开执行GRANT ALL PRIVILEGES ON *.* TO rootlocalhost; FLUSH PRIVILEGES;❌ 若报Table elderly_care.user doesnt exist说明数据库未初始化——此时需手动执行sql/elderly_care.sql项目根目录下建库建表。2.2 小程序前端避开「编译成功但白屏」的三大雷区打开微信开发者工具选择「不使用云服务」点击「导入项目」→ 选中miniprogram/目录。关键配置在project.config.jsonappid改为你自己的测试号登录 mp.weixin.qq.com 获取切勿用原作者的 AppID否则登录失败setting下urlCheck设为false关闭合法域名校验本地调试必需compileType保持miniprogram确认是小程序非插件。启动后若首页白屏按顺序排查打开「调试器」→「Console」看是否有fail: {errMsg:request:fail abort}—— 这是域名未配置回app.js检查baseUrl是否指向http://localhost:8080后端端口查看「Network」标签刷新页面看login请求是否返回{code:200,data:{token:xxx}}—— 若返回404说明后端/api/login接口未启动或路径写错本项目实际路径常为/user/login若请求成功但页面仍空打开「Wxml」面板检查index.wxml里wx:if{{hasLogin}}是否为false—— 此时需手动调用登录在「Console」输入wx.login()获取 code再用wx.request({url:http://localhost:8080/user/login, data:{code}})模拟登录。2.3 MySQL 数据库用一条命令完成初始化与权限加固不要手动建库执行项目自带 SQL 脚本最稳妥# 进入 MySQL 命令行确保已启动服务 mysql -u root -p # 输入密码后执行 source /path/to/your/elderly_care.sql; # ← 注意路径用绝对路径Windows 用反斜杠 # 然后立即加固权限防止答辩时被老师问「数据安全怎么保障」 CREATE USER elderly_applocalhost IDENTIFIED BY SecurePass123!; GRANT SELECT, INSERT, UPDATE ON elderly_care.* TO elderly_applocalhost; FLUSH PRIVILEGES;参数说明elderly_care.sql文件通常含 8 张表user,elderly,nurse,schedule,medication,health_record,emergency_contact,notice其中user表role字段用 tinyint(1) 存储角色0-管理员1-护工2-家属比 varchar 更省空间health_record表的blood_pressure字段用VARCHAR(20)存「120/80」而非两个 float避免小数精度争议——这是养老系统特有的数据存法。3. 核心功能落地家属查看健康数据、护工扫码巡房、管理员排班三段代码定乾坤本系统价值不在「能做」而在「做得准」。下面三段代码覆盖 80% 验收场景每段都带真实参数和避坑注释。3.1 家属端获取老人近 7 天血压/血糖趋势图小程序 JS Java Controller小程序pages/family/health/health.js中// 获取健康数据 getHealthData() { wx.request({ url: http://localhost:8080/api/health/trend, method: GET, data: { elderlyId: this.data.elderlyId, days: 7 }, // ← elderlyId 必须是数字不能是字符串 success: (res) { if (res.data.code 200) { this.setData({ trendData: res.data.data }); } } }); }Java 后端HealthController.javaGetMapping(/trend) public Result getTrend(RequestParam Long elderlyId, RequestParam(defaultValue 7) Integer days) { // 关键days 参数必须设 defaultValue否则前端不传 days 时直接 400 错误 ListHealthRecord records healthService.getTrend(elderlyId, days); // 日期格式化微信图表要求 YYYY-MM-DDMySQL 存的是 datetime需转换 ListMapString, Object result records.stream() .map(r - { MapString, Object m new HashMap(); m.put(date, r.getRecordTime().format(DateTimeFormatter.ofPattern(yyyy-MM-dd))); m.put(systolic, r.getSystolic()); // 收缩压 m.put(diastolic, r.getDiastolic()); // 舒张压 m.put(bloodSugar, r.getBloodSugar()); return m; }).collect(Collectors.toList()); return Result.success(result); }逻辑说明RequestParam Long elderlyId强制类型转换避免前端传字符串elderlyId: 123导致 Java 解析成0DateTimeFormatter用yyyy-MM-dd而非YYYY-MM-DD后者在周跨年时出错返回的result结构必须严格匹配小程序 ECharts 配置项否则图表不渲染。3.2 护工端扫码登记巡房小程序扫码 Java 接口校验小程序pages/nurse/scan/scan.js// 调起扫码 scanCode() { wx.scanCode({ success: (res) { const code res.result; // 格式如 elder_123_20240520 const parts code.split(_); if (parts.length ! 3 || parts[0] ! elder) { wx.showToast({ title: 二维码无效, icon: none }); return; } const elderlyId parseInt(parts[1]); const dateStr parts[2]; // 20240520 // 发送巡房记录 wx.request({ url: http://localhost:8080/api/schedule/checkin, method: POST, data: { elderlyId, dateStr, nurseId: getApp().globalData.userId } }); } }); }JavaScheduleController.javaPostMapping(/checkin) public Result checkIn(RequestBody CheckInRequest request) { // 1. 校验老人是否存在 Elderly elderly elderlyService.getById(request.getElderlyId()); if (elderly null) { return Result.fail(老人不存在); } // 2. 校验当日是否已巡房防重复提交 Schedule existing scheduleService.getByElderlyAndDate( request.getElderlyId(), LocalDate.parse(request.getDateStr(), DateTimeFormatter.BASIC_ISO_DATE) ); if (existing ! null) { return Result.fail(今日已巡房); } // 3. 插入新记录 Schedule schedule new Schedule(); schedule.setElderlyId(request.getElderlyId()); schedule.setNurseId(request.getNurseId()); schedule.setDate(LocalDate.parse(request.getDateStr(), DateTimeFormatter.BASIC_ISO_DATE)); schedule.setCheckInTime(LocalDateTime.now()); schedule.setStatus(1); // 1-已完成 scheduleService.save(schedule); return Result.success(巡房成功); }参数说明CheckInRequest类需定义Long elderlyId,String dateStr,Long nurseIdDateTimeFormatter.BASIC_ISO_DATE解析20240520为2024-05-20比yyyy-MM-dd更适配扫码生成的无分隔符日期status字段用数字而非枚举方便后期加「待审核」「已驳回」状态。3.3 管理员端智能排班Java Service 层算法骨架排班逻辑在ScheduleService.javaTransactional public void autoAssignShifts(Long departmentId, LocalDate startDate, LocalDate endDate) { // 获取该部门所有护工排除请假中 ListNurse nurses nurseService.listByDepartment(departmentId, false); // false未请假 // 获取该时段所有老人按护理等级分组 MapInteger, ListElderly elderlyByLevel elderlyService.groupByCareLevel(departmentId); // 核心规则1名护工最多管3名一级护理老人或5名二级护理老人 for (LocalDate date startDate; !date.isAfter(endDate); date date.plusDays(1)) { for (Map.EntryInteger, ListElderly entry : elderlyByLevel.entrySet()) { int careLevel entry.getKey(); ListElderly elders entry.getValue(); int nursePerGroup careLevel 1 ? 3 : 5; // 按老人数均分给护工向上取整 int nurseCount (int) Math.ceil((double) elders.size() / nursePerGroup); ListNurse assignedNurses pickNurses(nurses, date, nurseCount); // ← 实现轮休逻辑 // 分配每名护工分配 nursePerGroup 个老人 for (int i 0; i assignedNurses.size(); i) { int startIdx i * nursePerGroup; int endIdx Math.min(startIdx nursePerGroup, elders.size()); ListElderly batch elders.subList(startIdx, endIdx); batch.forEach(elderly - { Schedule s new Schedule(); s.setElderlyId(elderly.getId()); s.setNurseId(assignedNurses.get(i).getId()); s.setDate(date); s.setShiftType(1); // 1-早班2-晚班 scheduleMapper.insert(s); }); } } } }逻辑说明pickNurses()方法需实现「连续排班不超过 3 天」「同一护工不连上早晚班」等规则本项目默认用简单轮询nurses.get(i % nurses.size())但答辩时老师必问「如何保证公平性」——建议在Nurse实体加lastAssignedDate字段每次选人时优先挑lastAssignedDate最早的。4. 避坑指南答辩老师最爱问的 4 个致命问题以及血泪换来的解决方案这不仅是「能跑就行」的毕设更是要经得起现场演示、代码抽查、压力提问的交付物。以下 4 条是我在 3 所高校帮学生过审时被问到频率最高、当场翻车最多的坑按「现象 → 原因 → 解决」列清4.1 现象小程序登录后首页空白Console 显示Cannot read property name of undefined原因app.js中全局userInfo初始化为{}但首页index.wxml直接用了{{userInfo.name}}未加wx:if{{userInfo userInfo.name}}判断更深层是登录接口返回的data结构与前端期望不符如后端返回{user:{name:张三}}前端却按{name:张三}解析。解决前端所有userInfo.xxx访问前加wx:if或wx:else后端统一返回结构Result类的data字段必须是User对象非嵌套user字段验证用 Postman 调POST /user/login确认响应体为{code:200,msg:success,data:{id:1,name:张三,role:2}}。4.2 现象MySQL 导入elderly_care.sql报错ERROR 1071 (42000): Specified key was too long原因MySQL 5.7 默认innodb_large_prefixOFF而建表语句中username VARCHAR(50)加了UNIQUE KEYUTF8MB4 编码下 50*4200 字节 767 字节限制。解决方案一推荐修改 MySQL 配置my.cnf加两行[mysqld] innodb_large_prefixON innodb_file_formatBarracuda重启 MySQL 后执行ALTER TABLE user ROW_FORMATDYNAMIC;方案二快速直接改 SQL 文件将username VARCHAR(50)缩为VARCHAR(30)并删掉UNIQUE KEY用 Java 层校验唯一性。4.3 现象护工扫码后提示「巡房成功」但后台schedule表无记录原因RequestBody接收 POST 数据时若前端data是JSON.stringify({elderlyId:123})后端CheckInRequest类未加Data注解Lombok或elderlyId字段名与 JSON key 不一致如 JSON 是elderly_idJava 是elderlyId。解决确保CheckInRequest类有Data或手动写 getter/setter添加JsonProperty(elderly_id)注解若 JSON key 含下划线或统一约定前后端字段名全用驼峰小程序传{elderlyId:123}Java 接收private Long elderlyId;。4.4 现象答辩演示时老师用自己手机扫管理员二维码提示「无权限」原因小程序wx.getPhoneNumber获取手机号后后端仅校验「手机号存在」未校验「该手机号绑定的角色是否为管理员」或user表中role字段被误设为varchar导致role 0判断失效。解决登录接口增加角色校验if (!0.equals(user.getRole().toString())) { // 管理员 role0 return Result.fail(无管理员权限); }数据库user.role字段类型必须为TINYINT(1)插入时用INSERT INTO user VALUES (1,admin,123,0)严禁用字符串0。5. 进阶技巧让养老院真正在用的 3 个隐藏优化答辩加分项很多同学做到「功能完整」就停了但真正让系统从「毕设作品」变成「可用工具」的是那些藏在角落的细节优化。我帮养老院部署时发现这三点最被护工和管理员念叨5.1 小程序「息屏/切出」自动锁屏防老人误触微信小程序默认息屏后仍保持登录态老人看电视时手机放一边回来可能点错「紧急呼叫」。解决方案监听onHide生命周期30 秒后自动登出。在app.js中App({ onLaunch() { this.globalData.timer null; }, onHide() { // 息屏或切后台时启动倒计时 this.globalData.timer setTimeout(() { wx.clearStorageSync(); // 清除 token wx.reLaunch({ url: /pages/login/login }); // 强制回到登录页 }, 30000); // 30秒 }, onShow() { // 回到前台时清除定时器 if (this.globalData.timer) { clearTimeout(this.globalData.timer); this.globalData.timer null; } } });注意wx.reLaunch比wx.navigateTo更彻底避免历史页堆栈30 秒是平衡体验与安全的值——太短10秒护工觉得烦太长60秒起不到防护作用。5.2 Java 后端导出 Excel 时中文列名不乱码的终极写法养老院每月要交《老人健康汇总表》用EasyExcel导出时若不指定编码Excel 打开全是方块。正确做法GetMapping(/export) public void export(HttpServletResponse response) throws IOException { response.setContentType(application/vnd.ms-excel); response.setCharacterEncoding(utf-8); String fileName URLEncoder.encode(老人健康汇总表, UTF-8).replaceAll(\\, %20); response.setHeader(Content-disposition, attachment;filename fileName .xlsx); EasyExcel.write(response.getOutputStream(), HealthExport.class) .autoCloseStream(false) // 关键不自动关流由 Spring 管理 .sheet(健康数据) .doWrite(healthService.exportList()); }参数说明response.setCharacterEncoding(utf-8)解决 HTTP 头编码URLEncoder.encode(..., UTF-8)处理文件名中文autoCloseStream(false)防止 Spring 提前关闭 OutputStream 导致 Excel 损坏——这是 EasyExcel 3.x 的坑2.x 不需要。5.3 MySQL 查询优化老人健康记录分页不卡顿health_record表数据超 1 万条后SELECT * FROM health_record WHERE elderly_id123 ORDER BY record_time DESC LIMIT 20 OFFSET 1000会变慢。解决方案用「游标分页」替代OFFSET。Java Service 中// 第一页请求lastId 0 // 后续请求lastId 上一页最后一条 record.id public PageHealthRecord getPageByCursor(Long elderlyId, Long lastId, Integer size) { QueryWrapperHealthRecord wrapper new QueryWrapper(); wrapper.eq(elderly_id, elderlyId); if (lastId 0) { wrapper.lt(id, lastId); // ← 关键用主键 id 降序分页非时间字段 } wrapper.orderByDesc(id); return healthRecordMapper.selectPage(new Page(1, size), wrapper); }为什么有效id是主键B树索引查找快record_time可能有重复值导致分页错位lastId由前端传入上一页数据的id字段比page51更精准。最后说句实在的我当年毕设也折腾过养老系统凌晨三点改 MySQL 字符集、微信开发者工具反复重装、答辩前夜发现wx.getPhoneNumber在 iOS 上回调延迟——这些坑我都踩过。现在回头看最值得投入的不是炫技的算法而是让护工扫一次码就成功、让管理员导出的 Excel 打开就是中文、让老人子女点开小程序第一眼就看见「爸爸今天血压正常」。这套「Java 小程序 MySQL」组合不是最优解但它是经过养老院真实场景锤炼的「够用解」。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑