news 2026/9/24 23:55:53

基于微信小程序的留守宠物喂养管理系统设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于微信小程序的留守宠物喂养管理系统设计与实现

毕业设计这东西,每年选题都像在开盲盒。市面上那些库存管理系统、商城系统早就被做烂了,你答辩时老师看一眼题目就知道你用了什么模板。相比之下,“留守宠物喂养管理系统”是这几年我一直推荐给学生的选题:需求真实存在、功能边界清晰、技术栈覆盖全面,而且做出来之后是真的能拿去用的东西。

先说一下这个系统到底解决了什么问题。养猫养狗的人出差、回老家、临时加班,宠物没法带在身边,放在宠物店寄养不仅贵,还得担心宠物应激反应。所以一个能远程查看宠物状态、按计划定时喂食、记录进食情况的微信小程序,就成了刚需。这个项目恰好卡在了一个非常合适的位置:微信小程序做前端,后端用Java或者Node.js都行,数据用MySQL存,再加上硬件侧的定时喂食器(如果要做硬件联动的话),整个链路做下来,一个完整的毕设项目闭环就有了。

我之前带过几个学生做这个方向,今天就把整个项目的设计思路、关键代码、踩坑记录全部分享出来。

1. 项目定位与整体设计思路

1.1 为什么选微信小程序而不是App

这可能是你要做的第一个决定。我的建议非常直接:选微信小程序,别犹豫。

从用户角度看,微信小程序的打开成本几乎为零。用户不会为了喂个猫专门去应用商店下载一个App,但他们会为了等外卖顺手在微信里搜一下小程序。从开发角度看,小程序前端上手门槛低,WXML和WXSS的语法接近HTML和CSS,只要是写过网页的人都能快速进入状态。再加上微信自带的登录体系和消息推送机制,省掉了自己搭用户系统和短信服务的麻烦。

从毕设评审的角度看,微信小程序这个关键词本身就带着关注度。答辩老师看到你做的是小程序,第一反应是“这学生跟得上技术趋势”,而不是“又是传统Web那套”。

1.2 功能模块拆解:需求从哪来

做毕设最容易犯的错就是一上来就写代码。正确做法是先画清楚功能边界。我当时给学生的建议是分四个核心模块:

  • 宠物档案模块:添加、编辑、删除宠物信息(名字、品种、年龄、体重、饮食习惯备注)
  • 喂食计划模块:设定每日喂食时间、单次出粮量、喂食器状态反馈
  • 监控与记录模块:查看宠物的进食记录、(可选)视频画面或摄像头抓拍
  • 个人中心模块:用户登录、设备绑定、消息通知设置

这四个模块覆盖了从“创建宠物信息”到“查看喂食结果”的完整闭环。每一块拿出来都能在文档里写出一章,加起来内容量足够撑起一篇合格的毕业论文。

1.3 技术选型的底层逻辑

整个项目的主流技术栈是这个组合:

层级技术选型选择理由
前端微信小程序原生(或uni-app)原生语法稳定、调试方便,uni-app可兼顾多端
后端Spring BootJava生态成熟,毕业答辩被追问的概率低
数据库MySQL关系型数据库的经典选择,表结构设计好讲
接口协议RESTful API + JSON前后端分离的标准姿势
硬件联动ESP8266/ESP32(可选)如果做硬件方向,这是最便宜的方案

后端我推荐Spring Boot是有私心的。不是因为Java性能多好,而是因为答辩时老师大概率会问“为什么选这个框架”“Spring的IoC和AOP怎么体现的”,你用Spring Boot可以很自然地引出依赖注入、自动配置这些知识点,回答起来有东西可说。如果你更熟Node.js,改成Express或Egg也没问题,关键是自己弄得明白。

2. 数据库设计与接口规范

2.1 表结构怎么设计才合理

这套系统的表结构比一般的商城系统要简单,但有几张表的设计直接决定了后面功能好不好扩展。我建议核心表设计如下:

用户表(user):openid是微信小程序的唯一身份标识,必须加唯一索引。nickname、avatar_url用于展示个人资料,绑定设备编号字段可空,方便后面做设备解绑再绑定。

宠物表(pet):user_id关联用户表,pet_name、pet_type(猫/狗)、pet_weight、breed、birthday用于档案展示,feeding_note是自由文本字段,存“猫粮过敏”“每天加一次化毛膏”这类备注。

喂食计划表(feeding_plan):计划创建时一次性生成未来N天的计划记录,或者只在用户编辑时更新当天及之后的记录。每条记录包含计划时间、出粮克数、状态字段(待执行、已执行、已跳过),状态由后端定时任务更新。

喂食记录表(feeding_record):设备上报喂食完成后写入一条记录,包含实际喂食时间、出粮克数、剩余粮量、执行来源(自动/手动)。这张表的粒度决定了你之后能做多细的统计。

设备表(device):device_id作为物理设备的唯一标识,status字段表示在线/离线,last_online_time用于展示设备状态。如果你不做硬件,这表可以简化成用户直接维护一个“喂食器状态”。

2.2 接口怎么设计才清晰

接口设计遵循一个原则:让前端调用起来不用想太多。以下是核心接口清单:

  • POST /api/user/login:小程序wx.login获取code,后端用code换取openid,首次登录自动注册
  • GET /api/pet/list:获取当前用户的宠物列表
  • POST /api/pet/add:新增宠物资料
  • PUT /api/pet/update:修改宠物资料
  • DELETE /api/pet/delete:删除宠物
  • GET /api/plan/list?petId=xxx&date=xxx:按日期获取喂食计划
  • POST /api/plan/save:创建或修改喂食计划
  • POST /api/plan/execute:手动触发一次喂食
  • GET /api/record/list?petId=xxx&pageNum=1&pageSize=10:分页查询喂食记录
  • GET /api/device/status:获取绑定设备状态

注意接口命名要语义化,参数要校验,响应格式保持统一。我习惯统一返回Result对象,包含code(200成功,500失败)、message和data三个字段。这样前端处理异常就只需要判断code,省心很多。

3. 微信小程序前端实现的核心细节

3.1 登录流程别再用老一套了

现在很多教程还在让你用wx.getUserInfo去拿用户头像昵称,这已经行不通了。微信官方早就调整了规则, getUserInfo弹窗被砍掉,现在是默认获取灰色头像和“微信用户”昵称。

正确的做法是:

// app.js 中封装登录逻辑 const login = () => { wx.login({ success: (res) => { if (res.code) { // 将code发送到后端,后端通过code换openid wx.request({ url: 'http://localhost:8080/api/user/login', method: 'POST', data: { code: res.code }, success: (response) => { const { token, userId } = response.data.data wx.setStorageSync('token', token) wx.setStorageSync('userId', userId) } }) } } }) }

用户头像和昵称要单独引导用户去完善:点击头像时弹出wx.chooseMedia选择图片,上传到自己的对象存储,再把URL存到数据库。这也是一个可以写进文档的细节:为什么不能用open-type="getUserInfo"直接拿头像,因为隐私协议收紧后,很少会有用户愿意授权。

3.2 定时任务的“坑”与解决方案

这里说一个小程序端的经典坑。很多学生会想用小程序的定时器setInterval去定时触发喂食,但这在微信小程序里根本不靠谱:小程序在后台时定时器会被挂起。你的宠物喂食计划必须由后端执行。

后端的定时任务方案也很简单,在Spring Boot里用@Scheduled注解:

@Component public class FeedingTask { @Autowired private FeedingPlanMapper planMapper; @Autowired private FeedingRecordMapper recordMapper; // 每分钟执行一次,检查是否有需要执行的喂食计划 @Scheduled(cron = "0 * * * * ?") public void checkPlans() { List<FeedingPlan> plans = planMapper.selectByStatusAndTime( "WAITING", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm") ); for (FeedingPlan plan : plans) { // 发送HTTP请求到喂食器端 DeviceResponse resp = deviceClient.executeFeed(plan.getDeviceId(), plan.getFeedAmount()); if (resp.isSuccess()) { plan.setStatus("EXECUTED"); // 记录喂食信息 recordMapper.insert(...); } else { plan.setStatus("FAILED"); // 发送告警通知给用户 wxMessageService.send(plan.getUserId(), "喂食失败,请检查设备"); } planMapper.updateById(plan); } } }

这个定时任务的粒度设置为“每分钟检查一次”,相比每秒轮询大大降低了对数据库的压力。计划表里的执行时间精确到分钟就足够了。

3.3 前端页面开发顺序建议

页面开发顺序直接决定了效率。我的建议按这个顺序来:

先做宠物列表页,这是用户进入小程序后的首页,需要显示宠物卡片(头像、名字、品种、体重)和“添加宠物”按钮。接着做宠物档案编辑页,把表单组件调稳定了,后面套用别的表单就顺畅了。

然后做喂食计划页,这是整个系统的核心功能页。这里有个设计要点:喂食计划的展示建议按周视图排布,周一到周日,每天可以单独设置喂食时间。用表格布局做这个比时间轴更清晰。

最后做动静分离的页面:喂食记录列表用滚动列表,每行显示时间和出粮克数;我的页面用普通卡片布局,放设置入口、设备绑定、关于页面。

3.4 网络请求封装

原生小程序请求有点繁琐,建议封装一个request工具:

// utils/request.js const request = (url, method, data) => { return new Promise((resolve, reject) => { wx.request({ url: `https://your-api-server.com${url}`, method, data, header: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${wx.getStorageSync('token')}` }, success: (res) => { if (res.data.code === 200) { resolve(res.data.data) } else { wx.showToast({ title: res.data.message, icon: 'none' }) reject(res.data) } }, fail: (err) => { // 网络异常时的统一处理 wx.showToast({ title: '网络连接失败', icon: 'none' }) reject(err) } }) }) }

别小看这个封装,它会让你的页面代码干净得多。每个页面里只需要写:

const list = await request('/api/pet/list', 'GET') setData({ petList: list })

而不是每次都去写一遍wx.request的回调、错误处理和loading状态。

4. 后端关键逻辑与硬件联调(可选方案)

4.1 用户认证的完整链路

微信小程序后端的用户认证流程是固定套路:

  1. 前端调用wx.login拿到临时凭证code
  2. 前端把code传给后端
  3. 后端通过HTTPS请求微信接口:https://api.weixin.qq.com/sns/jscode2session,带上appid、secret和code
  4. 微信返回openid和session_key
  5. 后端查数据库,有则更新登录信息,无则注册新用户
  6. 后端生成自定义token(可以用jwt或session),返回给前端

这里要注意的坑是:appid和secret绝对不能写到前端代码里,否则任何人反编译小程序都能拿到你的secret,理论上可以冒充你的小程序做坏事。正确做法是通过后端转发,由后端来存secret。

4.2 硬件联调的最后一步:串口通信能不做就不做

如果你选择做“硬件联动”,最省心的方式是:买一个带WiFi的智能喂食器(市场价大约100到200元),通过它的开放API接口对接你的后端,而不是自己去写ESP8266的固件做串口通信。

原因很现实:纯软件方向的学生,搞单片机要看很多焊接和电烙铁知识;纯硬件方向的学生,又会卡在后端接口上。用现成的智能喂食器,把对接的重点放在“你的后端如何通过HTTP请求操作设备”,一样可以讲清楚整个物联网闭环,而且精力能集中在毕业设计真正考核的软件工程能力上。

如果你一定要自己用ESP8266做硬件,联调时的关键代码大致是这样的思路:

#include <ESP8266WiFi.h> #include <HTTPClient.h> void setup() { WiFi.begin("your-wifi-ssid", "your-wifi-password"); while (WiFi.status() != WL_CONNECTED) { delay(500); } // 每10秒轮询一次后端,查询是否有新的执行指令 } void loop() { if (WiFi.status() == WL_CONNECTED) { HTTPClient http; http.begin("http://your-server.com/api/device/command"); int httpCode = http.GET(); if (httpCode > 0) { String payload = http.getString(); // 解析指令,触发舵机转动出粮 } http.end(); } delay(10000); }

这种轮询方案虽不优雅,但胜在简单稳定。真正生产级的做法是让后端通过MQTT协议推送指令到设备,这个对于毕设来说有点超纲,能写进文档里提一下就行。

4.3 消息通知怎么实现

用户最关心的是“喂食是否成功”这个结果。微信小程序里推送订阅消息是合适的方案,不过需要解决模板ID和用户授权的问题。

// 小程序端请求订阅消息授权 wx.requestSubscribeMessage({ tmplIds: ['模板ID'], success: (res) => { if (res['模板ID'] === 'accept') { // 用户同意授权,可以发送订阅消息 request('/api/subscribe/register', 'POST') } } })

服务端在计划执行完成或异常时,调用微信的订阅消息接口:

curl -X POST "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "touser": "OPENID", "template_id": "模板ID", "page": "pages/record/record", "data": { "thing1": { "value": "小乖" }, "time2": { "value": "12:30" }, "thing3": { "value": "出粮15克,剩余粮量充足" } } }'

有一个实际的限制需要提前知道:微信订阅消息是一次性的。用户授权一次只能收到一条消息,不能像公众号模板消息那样无限制推送。因此对于“喂食成功”这种高频场景,不能每次都推送。实际设计中,我建议只推送“异常告警”和“手动执行的结果”,计划成功执行时不做推送,而是在小程序首页展示,让用户自行点开查看。

5. 常见问题与排查技巧实录

5.1 制作流程中会遇到的典型问题

先盘点一下学生在做这个题目时最常见的问题:

问题场景现象排查思路与解决办法
后端启动了但小程序请求失败提示“request:fail -2:net::ERR_FAILED”开发阶段后端地址要加 https,但在本地调试必须勾选“不校验合法域名”,小程序开发者工具右上角详情-本地设置里打开
微信登录拿不到openid后端日志显示code无效检查appid和secret是否填写正确,确认不是用的测试号来对接正式小程序后台
计划保存了但到点不执行数据库状态没有更新检查@Scheduled是否启用(启动类要加@EnableScheduling),确认服务器时间与本地时间一致
请求头跨域报错浏览器控制台CORS报错后端加@CrossOrigin注解,或在配置类中注册全局CORS配置
数据库时间字段差8小时存储时间比实际时间晚8小时连接池URL里加serverTimezone=Asia/Shanghai,同时检查服务器时区设置
订阅消息发送时报43101用户拒绝了授权或已超过一次性限制引导用户重新在小程序内授权,或换一个模板场景重新触发

第一个问题概率最高。很多学生第一次用开发者工具,不知道默认情况下小程序不能请求http接口。这里再次强调:正式发布的小程序只能访问HTTPS接口且域名必须备案;但开发和真机调试阶段,可以在工具里勾选“开发环境不校验合法域名”。

5.2 微信开发者工具的3个实用姿势

这3个技巧是提升调试效率的关键,常规教程很少提到:

  • 利用“模拟操作”面板里的“编译模式”:可以自定义启动页面的参数,比如直接进入编辑宠物资料页,而不用每次从首页点好几层才能到。非常适合调试某个深层次页面时使用。
  • “真机调试”选择“USB调试”或“远程调试”:当你发现模拟器上一切正常,但真机上数据加载出来是空白时,可以优先通过真机调试模式看Console面板的输出,能直接看到具体报错是接口挂了还是渲染出问题。
  • “缓存”面板可以一键清除全部缓存:开发时经常遇到小程序代码更新了,但运行结果还是旧数据,多半是Storage缓存没清。通过“清缓存”一键完成,省得反复手动删Storage。

5.3 有没有必要做多端兼容(uni-app版本)

这个问题的答案取决于你要不要参加比赛或后续继续维护。如果你做的是纯毕业设计,这个不是刚需,微信小程序原生自己做一遍就够了。但如果你要参加“互联网+”之类的创新创业比赛,多端发布(微信小程序、支付宝小程序、H5、App)会显著加分,这时候考虑用uni-app重写前端是有价值的。

用uni-app的代价是:你可能会遇到一些编译层面的问题(比如某些原生组件在uni-app里需要特殊适配),以及很多教程都是针对原生写法的,迁移过去需要一定的排查能力。建议是:毕业设计就原生写,省时省力;参加比赛可以冲一下uni-app,作为创新点写进文档。

6. 毕业设计过程中自己踩过的坑

6.1 需求膨胀是一个巨大的坑

这个项目管理系统的方向很容易让人上头:要不要加视频监控?要不要加语音呼唤?要不要加自动铲屎?我的建议很明确:除非你的毕设题目明确要求必须包含这些,否则统一砍掉。你首先需要保证的是核心流程(登录-建档-设置计划-执行记录-结果展示)完整跑通。

做减法是我带学生时反复强调的点。一个能稳定跑完核心流程的毕设,拿到的评分一定高于一个做了5个功能但每一个都Bug连篇的毕设。核心流程做好了,有余力再锦上添花。视频监控功能牵扯到视频流、对象存储、小程序live-player组件兼容性,复杂度是以指数级增长的,不是一星期能磨出来的。

6.2 数据库的初始化脚本一定要留好

很多学生喜欢直接在Navicat里面手动点着建表,进程到了最后忘了留存SQL脚本,换一台电脑就要重头建表。正确做法是写一个schema.sql,存放在项目代码库里,里面包含建库建表语句和基础测试数据。这样不管换开发机、部署服务器、还是最后交给导师演示,都能一键初始化。

核心SQL脚本示例:

-- 用户表 CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `openid` varchar(64) NOT NULL, `nickname` varchar(50) DEFAULT '微信用户', `avatar_url` varchar(255) DEFAULT NULL, `device_id` varchar(64) DEFAULT NULL, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_openid` (`openid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; -- 喂食计划表 CREATE TABLE `feeding_plan` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `user_id` bigint(20) NOT NULL, `pet_id` bigint(20) NOT NULL, `device_id` varchar(64) NOT NULL, `plan_time` varchar(16) NOT NULL COMMENT '计划喂食时间 HH:mm', `feed_amount` int(11) NOT NULL COMMENT '出粮克数', `status` varchar(20) NOT NULL DEFAULT 'WAITING', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='喂食计划表';

多花这一点时间,后期能省掉很多琐碎的麻烦。

6.3 工作量展示上留意这几个细节

最后说一个答辩和文档上的经验。

  • 截图配时序图:论文里的功能展示不要只放小程序页面截图,加上接口调用时序图(比如用户发起喂食计划-后端保存-定时任务触发-设备执行-前端展示记录),会显得你对系统整体运行逻辑有清晰的认知。
  • 过程文档按版本迭代命名:答辩时老师在评审表上会看你的开发日志或技术报告。如果能把过程文档做成“V1.0-需求分析→V2.0-数据库设计→V3.0-前后端联调→V4.0-功能优化”这种版本线,直观体现你的工作是在递进的。
  • 演示前一定要准备一台备用手机:真机演示时,最常见的翻车情况是小程序需要重新登录、扫码调试后网络断了、或手机电量不足。用备用机提前配置好测试账号,避免现场手忙脚乱。

这个选题最大的乐趣在于,你做的东西是真的可以拿去喂家里那只猫的。我自己的那只橘猫,就是被这套系统喂胖的。当你出差在外,打开小程序看到猫主子在食盆前吃得正香的时候,那种成就感不是一纸文凭能替代的。如果你也在做这个方向的毕设,希望这篇文章能帮你少走一些弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 23:55:52

转型实战项目十六:构建一个全自动多 Agent 智能混沌工程与故障演练平台

转型实战项目十六&#xff1a;构建一个全自动多 Agent 智能混沌工程与故障演练平台在传统稳定性测试与 SRE 专家转型为 AI 智能体架构师的高级进阶实战中&#xff0c;“亲手构建一个企业级、跨多可用区 K8s 集群、全自动设计混沌实验、精准注入网络/硬件故障、并智能评估全链路…

作者头像 李华
网站建设 2026/9/24 23:55:49

4200张果蔬图图像分类实战:PyTorch迁移学习与避坑指南

简介&#xff1a;面向图像分类任务&#xff0c;这份数据集提供已标注的常见果蔬图像&#xff0c;覆盖香蕉、苹果、梨、葡萄、橙子、黄瓜、胡萝卜、辣椒、洋葱、土豆等36个类别&#xff0c;共约4200张图片。json文件保存了36个类别的名称对应关系&#xff0c;图片已预处理&#…

作者头像 李华
网站建设 2026/9/24 23:55:34

AI Agent无人值守实战:定时任务的可靠性设计与效果验证

做无人值守 Agent 有个很有意思的分水岭&#xff1a;开发环境里跑通一次&#xff0c;和让它每天凌晨自动跑完还能自己处理异常&#xff0c;完全是两码事。我最近把一个定时自动化任务从“人盯着跑”改造成“无人值守”&#xff0c;中间踩的坑比我预想的多一整个量级。这篇文章不…

作者头像 李华
网站建设 2026/9/24 23:55:12

气球COCO数据集:Mask R-CNN实例分割训练全流程指南

简介&#xff1a;这是一份面向计算机视觉入门与进阶学习者的气球实例分割数据集&#xff0c;基于 Mask R-CNN 构建并已完整转换为 COCO 格式&#xff0c;可直接放入最新 MMDetection 框架中训练与测试&#xff0c;免去自行标注和格式转换的繁琐步骤。资源包大小 36.89MB&#x…

作者头像 李华
网站建设 2026/9/24 23:54:48

OpenNI多Kinect同步实战:USB隔离、双上下文与时间戳对齐

简介&#xff1a;本资源是一份面向计算机视觉与多传感器开发者的实用技术文档&#xff0c;聚焦于使用OpenNI框架在单台PC上同时读取多个Kinect设备的完整实现方案&#xff0c;适用于机器人感知、三维重建、多人交互等需要多视角深度数据的进阶应用场景。文档以C代码为核心&…

作者头像 李华