简介:这份微信小程序毕业设计资源以社区养老服务为业务场景,面向计算机及相关专业的学生及需要完成毕设或课程设计的开发者,完整覆盖前端页面、后台管理与服务端逻辑。压缩包内共包含1707个文件,总大小约84.57MB,前端页面由wxml、wxss与js构成,后台管理界面基于vue与js实现,Java文件承担服务端请求处理,SQL脚本提供数据库结构,png/jpg及svg为界面图片与图标,mp4演示视频可辅助理解运行效果,bat脚本则便于快速启动部署。项目功能完善、界面美观,代码注释清晰,新手也能看懂;经严格调试可稳定运行,简单部署后即可使用。目前已有210人学习浏览,适合参考其整体架构与模块设计,在此基础上进行二次开发或功能扩展,是一份高分毕业设计项目的完整参考。
1. 社区养老小程序毕业设计:为什么“服务闭环”比页面数量更决定评分
一个挂着“社区养老服务”名字的微信小程序毕业设计,常见的样子是这样的:首页放几张轮播图,底下排列着“助餐、助洁、助医”几个图标,点击进去是一张静态服务介绍页,个人中心能看到绑定好的老人档案。看着功能齐全,但答辩时老师一问“工单状态是怎么流转的”“健康数据异常怎么通知家属”,现场就冷场。这个标题里的关键词,真正拉开分数差距的不是界面好不好看,而是你交付的是一套“能跑通完整业务流程”的系统,还是一堆彼此孤立的页面。本文就按养老服务的真实业务线,把源码结构、数据库设计、接口逻辑和演示视频的做法拆开讲,目标是让拿到这个方向的人,从“有个界面”做到“能讲明白、敢演示、扛得住追问”。
2. 技术选型与工程骨架:小程序端、服务端、数据库各层怎么配
2.1 小程序端选型:原生框架还是 uniapp
社区养老小程序这类题目,小程序端用原生微信小程序框架就够了。原生框架的优点是工具链短、调试直观,wx.request、wx.getLocation、wx.login这些接口都是现成的,答辩时被问到底层原理也能说得更清楚。如果组里有人已经会用 uniapp,或者想顺便把代码移植到其他平台,选 uniapp 也不算错,但要注意 uniapp 在微信小程序里的生命周期和原生不完全一致,比如onShow触发时机、自定义导航栏的适配都要额外处理,毕业设计阶段反而会增加排错成本。
我的建议是:单人完成、时间紧张,直接用原生小程序;有团队协作或跨端需求,才考虑 uniapp。这个决策本身也可以写进论文的“技术选型”章节,属于加分项。
2.2 服务端与数据库选型
服务端常见做法是 Spring Boot 或者 Node.js Express,两者都行,关键是看你更熟悉哪个。Spring Boot 生态成熟,MyBatis-Plus 做增删改查非常快,适合 Java 方向的学生;Node.js 上手轻,配合express和mysql2包,前后端都用 JavaScript,心智负担小。数据库几乎固定选 MySQL,理由很简单:社区养老的数据量级在毕业设计范围内用不上 PostgreSQL 或 Oracle,MySQL 的安装、可视化工具、网上资料都是最多的,遇到问题容易搜到答案。
连接池配置是经常被忽略的点。Spring Boot 里默认的 HikariCP 不需要额外配置就能跑,但如果你用 Node.js 的mysql2,一定要用连接池而不是单连接:
const mysql = require('mysql2/promise'); const pool = mysql.createPool({ host: 'localhost', user: 'root', password: 'your_password', database: 'community_care', waitForConnections: true, connectionLimit: 10, queueLimit: 0, enableKeepAlive: true, keepAliveInitialDelay: 0 }); module.exports = pool;这里的connectionLimit控制最大连接数,毕业设计并发量很低,10 就够了,设太大会占用 MySQL 默认的最大连接数,反而把本机数据库拖慢。waitForConnections设为true表示连接池满了就排队等待,避免并发请求直接报错。答辩时若被问到“数据库连接怎么管理”,这套配置就是现成的答案。
2.3 工程目录结构与启动顺序
整套系统由三个工程组成:小程序前端、服务端、数据库脚本。实际交付时把三个目录放在同一个项目根目录下,命名尽量直白:
community-care/ ├── miniprogram/ # 微信小程序前端 │ ├── pages/ │ ├── utils/request.js # 封装的请求工具 │ └── app.json ├── server/ # 服务端 │ ├── src/main/java/... # 或 app.js │ └── pom.xml # 或 package.json ├── database/ │ ├── init.sql # 建库建表脚本 │ └── seed.sql # 演示用初始化数据 └── docs/ ├── 答辩PPT提纲.md └── 演示视频脚本.md启动顺序是:先导入 init.sql 和 seed.sql 初始化数据库,再启动服务端,最后用微信开发者工具导入 miniprogram 目录。注意这里必须强调一句:数据库脚本是毕业设计的“命根子”。很多人重装系统后项目跑不起来,就是因为当时建表是手工点的,没有留存脚本。从第一天就把所有表结构写进 init.sql,每次改动同步更新,这是最高性价比的习惯。
3. 数据库与服务端接口:把老人档案、工单、健康数据串成一张可演示的网
3.1 核心数据表设计
社区养老业务的最小闭环是:家属绑定老人 → 家属下单服务 → 平台派单给护工 → 护工完成服务 → 家属确认并评价。围绕这条线,核心表至少要六张:用户表、老人档案表、家属绑定关系表、服务项目表、工单表、健康数据表。
-- 老人档案表 CREATE TABLE `elder` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL COMMENT '老人姓名', `gender` TINYINT NOT NULL DEFAULT 1 COMMENT '1男 2女', `age` INT NOT NULL, `address` VARCHAR(200) NOT NULL COMMENT '居住地址', `contact_name` VARCHAR(50) NOT NULL COMMENT '紧急联系人', `contact_phone` VARCHAR(20) NOT NULL, `chronic_disease` VARCHAR(500) DEFAULT NULL COMMENT '慢性病史,逗号分隔', `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_address` (`address`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='老人档案表'; -- 服务工单表 CREATE TABLE `service_order` ( `id` INT NOT NULL AUTO_INCREMENT, `order_no` VARCHAR(32) NOT NULL COMMENT '订单号,按时间戳生成', `elder_id` INT NOT NULL COMMENT '关联老人档案', `service_type` TINYINT NOT NULL COMMENT '1助餐 2助洁 3助医 4陪诊', `status` TINYINT NOT NULL DEFAULT 0 COMMENT '0待接单 1已接单 2服务中 3已完成 4已取消', `appoint_time` DATETIME NOT NULL COMMENT '预约服务时间', `address` VARCHAR(200) NOT NULL, `remark` VARCHAR(500) DEFAULT NULL, `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_order_no` (`order_no`), KEY `idx_elder_status` (`elder_id`, `status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='服务工单表';字段注释必须写,团队协作和答辩都要看。status用 TINYINT 存数字状态而不是字符串,一是省空间,二是代码里用常量映射更清晰。老人档案表故意加了idx_address索引,是因为“按小区查找老人”是社区服务的典型查询场景,这个索引在答辩时可以拿来解释设计理由。
健康数据表记录的是老人每次测量的血压、心率等指标,注意要把测量时间设为DATETIME类型,不能用VARCHAR。很多人在这一步图省事存字符串,后面做“最近一周趋势图”时才发现排序和日期计算全是坑,这部分在第五章会展开讲。
3.2 服务接口清单与权限设计
接口层按角色划分三组:家属端接口、护工端接口、管理端接口。用 Spring Boot 写 Controller,每个接口的路径和含义如下表:
| 角色 | 接口路径 | 方法 | 作用 |
|---|---|---|---|
| 家属 | /api/elder/bind | POST | 绑定老人档案 |
| 家属 | /api/services/list | GET | 获取服务项目列表 |
| 家属 | /api/order/create | POST | 创建服务工单 |
| 护工 | /api/order/take | POST | 接单 |
| 护工 | /api/order/complete | POST | 完成服务 |
| 家属 | /api/order/confirm | POST | 确认并评价 |
| 家属 | /api/health/list?elderId= | GET | 查询健康数据 |
权限设计不用上 Spring Security,太重。做法是在拦截器里校验请求头带的token,查一下用户角色,家属只能操作自己绑定的老人数据,护工只能操作派给自己的工单。这条规则写入答辩讲稿里,属于“业务安全”的加分点。
3.3 关键 SQL 与调试技巧
工单流转中最常被问的是“如何查某个老人最近三个月的服务记录”。这个 SQL 要熟练:
SELECT o.order_no, o.status, o.appoint_time, s.name AS service_name FROM service_order o LEFT JOIN service_item s ON o.service_type = s.id WHERE o.elder_id = ? AND o.appoint_time >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH) ORDER BY o.appoint_time DESC;DATE_SUB(CURDATE(), INTERVAL 3 MONTH)是标准写法,直接在 SQL 里算时间范围,比在代码里拼字符串再传进来更安全。调试阶段如果发现查询慢,用EXPLAIN SELECT ...看是否命中索引,这个习惯可以写进论文的“性能优化”部分。
服务端写完后,用 Postman 或 Apifox 把每个接口跑通一遍,导出接口文档放进 docs 目录。这一步的价值在答辩时体现得很直接:老师问“系统一共多少个接口”,你不用现场数页面,直接打开文档报数。
4. 小程序端核心实现:request封装、首页服务列表与下单流程
4.1 全局request封装与拦截器
小程序端所有请求都走封装好的request.js,不要在每个页面里直接wx.request。统一封装后有三个好处:请求头自动带 token、错误码统一提示、未来换接口域名只改一个文件。
// utils/request.js const BASE_URL = 'http://localhost:8080/api'; function request(path, method = 'GET', data = {}) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + path, method: method, data: data, header: { 'Content-Type': 'application/json', 'token': wx.getStorageSync('token') || '' }, success: (res) => { if (res.statusCode === 200 && res.data.code === 0) { resolve(res.data.data); } else if (res.statusCode === 401) { wx.showToast({ title: '登录已过期', icon: 'none' }); wx.navigateTo({ url: '/pages/login/login' }); reject(res); } else { wx.showToast({ title: res.data.msg || '请求失败', icon: 'none' }); reject(res); } }, fail: (err) => { wx.showToast({ title: '网络异常', icon: 'none' }); reject(err); } }); }); } module.exports = { get: (path, data) => request(path, 'GET', data), post: (path, data) => request(path, 'POST', data) };代码里有两个关键设计:一是 token 从本地缓存读取并写进每次请求的 header,保证登录态能传递到后端;二是统一判断res.data.code === 0,这是前后端约定好的业务码,不等于 HTTP 状态码。很多翻车现场就是后端返回了 HTTP 200 但业务失败,前端没判断业务码,页面静默出错。
注意BASE_URL在开发阶段指向本机 IP,比如http://192.168.1.100:8080/api,因为localhost在手机预览时指向手机自己而不是电脑。这里也是新人最常踩的坑之一。
4.2 首页服务列表与按距离排序
首页要展示可预约的服务项目,并且按距离排序,这需要前端拿到老人的经纬度,传给后端做排序。核心代码在页面里这样写:
// pages/home/home.js const request = require('../../utils/request.js'); Page({ data: { services: [], latitude: null, longitude: null }, onLoad() { this.getLocationAndLoadServices(); }, getLocationAndLoadServices() { wx.getLocation({ type: 'gcj02', success: (res) => { this.setData({ latitude: res.latitude, longitude: res.longitude }); this.loadServices(res.latitude, res.longitude); }, fail: () => { wx.showToast({ title: '定位失败,使用默认排序', icon: 'none' }); this.loadServices(null, null); } }); }, loadServices(lat, lng) { request.get('/services/list', { lat, lng }).then((list) => { this.setData({ services: list }); }); } });这里用gcj02坐标系是微信官方的要求,传给后端后,后端用 Haversine 公式计算距离排序。如果定位失败,前端会降级为默认排序,而不是卡在页面里转圈,这个兜底逻辑在答辩演示时很有用——现场定位经常失败,你提前做好了容错,就不会尴尬。
4.3 下单与工单状态流转
家属选择服务后提交订单,核心代码集中在createOrder里。这里最容易被忽略的是“预约时间”的校验:不能选过去的时刻。
// pages/service/service.js submitOrder() { const elderId = this.data.selectedElder.id; const serviceType = this.data.currentService.type; const appointTime = this.data.appointTime; if (!elderId) { wx.showToast({ title: '请先绑定老人', icon: 'none' }); return; } if (new Date(appointTime).getTime() < Date.now()) { wx.showToast({ title: '预约时间不能早于当前时间', icon: 'none' }); return; } request.post('/order/create', { elderId, serviceType, appointTime, address: this.data.selectedElder.address, remark: this.data.remark }).then((res) => { wx.navigateTo({ url: '/pages/order/detail?orderNo=' + res.orderNo }); }); }这段逻辑体现的是“前端校验只是体验优化,后端校验才是安全底线”。不要只在前端判断时间,后端 Controller 里也要用同样的规则再校验一次。答辩时把这个点讲出来,老师会认为你懂生产环境的逻辑。
工单状态流转的后端逻辑建议用一个简单的状态机:待接单 → 已接单 → 服务中 → 已完成 → 已评价。每个状态迁移都做合法性判断,比如“已完成”的工单不能被“接单”,否则数据就乱了。这个状态机写进论文的“系统设计”章节,是很好的设计亮点。
5. 毕业设计避坑指南:从真机白屏到答辩演示的5个高发雷区
5.1 现象:真机预览白屏,接口请求全失败
原因:开发者工具里勾选了“不校验合法域名”,但真机预览时这个选项不生效,而所有请求地址还是http://开头。解决:开发阶段把BASE_URL改成电脑的局域网 IP,并在微信开发者工具的项目设置里勾选“不校验合法域名”;如果演示用真机,记得在后台配置 request 合法域名,或临时用“开发版”加“调试模式”绕过。
5.2 现象:定位授权被拒,页面卡死在 loading
原因:wx.getLocation没有在app.json里声明需要的权限,或者用户点击了“拒绝”。解决:在app.json中加入requiredPrivateInfos字段声明定位,并在getLocation的fail回调里做降级处理,就像第四章代码里写的那样,而不是把错误吞掉。
另一个和定位相关的高发问题:iPhone 和安卓在定位权限弹窗的文案要求不同,部分基础库版本要求开发者填写用途说明,否则直接报错。这个说不清是微信的“玄学”,但解决路径是固定的——去官方的更新日志查对应版本要求。
5.3 现象:页面数量够,但业务流程走不通
原因:只做了增删改查,没有把“下单-接单-完成-评价”串起来。这是养老类毕业设计最常见的翻车点。解决:先画业务流程图,再把流程走通,最后补页面。很多人顺序反了,先做一堆页面,最后发现订单状态不联动,只能熬夜返工。
5.4 现象:健康数据趋势图的时间轴乱序
原因:MySQL 里把测量时间存成了VARCHAR,按字符串排序时'2025-01-02'会和'2024-12-30'错位。解决:数据表设计阶段全部用DATETIME类型;已经翻车的,用STR_TO_DATE函数转换后重新存储,这一步是血泪经验。
5.5 现象:演示视频里的数据一看就是假的
原因:测试数据都是“张三、李四、测试1、测试2”,地址写成“某某路”,毫无真实感。解决:在seed.sql里准备 10 个完整的老人档案,姓名、慢性病史、居住地址、最近一周的健康数据全部编成合理的样本,并且保证工单状态有“待接单”“服务中”“已完成”三种同时存在。演示时打开数据库管理工具,把表数据展现在视频里,这个细节会让评分明显改观。
6. 把演示视频拍成加分项:脚本、话术与数据准备技巧
演示视频不需要长,8 到 12 分钟最合适。结构上固定四段:系统架构与数据库展示、家属端功能演示、护工端功能演示、管理端与数据看板。前 30 秒先展示init.sql里所有表的关系,用 PowerDesigner 或 MySQL Workbench 导出 ER 图,这是“高分项目”里最直观的加分项。
视频录制时用模拟器但不要开到最大窗口,用微信开发者工具默认尺寸,字号清晰。操作鼠标时每个动作停 1 秒再点击,方便评审看清路径。关键节点把光标移到按钮上停留一下,配合口头念出预期结果,比如“点击接单,状态从待接单变为已接单”。拍摄前把完整脚本写成一页纸念熟,不要临场即兴。
最后提醒一点:演示视频里一定要有一个“异常处理”镜头,比如故意输入错误手机号、选择过去的时间点,把前端弹窗展示出来。这比十页文档更证明系统是真人测试过的。我自己的习惯是每次录视频前先跑一遍完整脚本,把失败路径也跑一遍,遇到报错先修再录。这套方法帮我从“页面合集”走到“能扛住追问”的程度,希望帮到你。
本文还有配套的精品资源,点击获取