简介:这是一套面向计算机专业本科生的毕业设计级微信小程序实战项目,聚焦奶茶店自助点餐场景,解决传统APP安装门槛高、用户留存低的问题,助力开发者掌握小程序前端+SpringBoot后端+MySQL数据库的全栈开发能力。资源包共774个文件,40.2MB,涵盖131个Vue组件(用于管理后台界面)、114个Java后端服务类(含Controller/Service/Entity层)、125张PNG/WebP图片与162个SVG图标(支撑小程序UI)、66个JS/WXML/WXSS文件(小程序端逻辑与样式),以及SQL建表脚本、开题报告、完整毕业论文和3段MP4演示视频。已有374人学习下载,内容结构完整:含可一键运行的bat脚本(install/run/build)、带注释的SpringBoot配置(yml/properties)、模块化的小程序页面目录及后台管理功能源码,特别适合课程设计参考、毕设选题复用或全栈技术整合训练。
1. 奶茶店自助点餐小程序:不是Demo,是能跑通「下单→支付→后厨接单→状态同步」全链路的毕业设计实战包
你手头那份写着“毕业设计”的压缩包,大概率不是拼凑的静态页面——它真能扫码进店、选珍珠波霸、加冰少糖、微信支付成功、厨房小票机自动吐单、店员在后台看到“订单号#20240517-083”正等待制作。这不是PPT里的流程图,而是基于微信小程序原生框架 + SpringBoot 2.7.x(非SpringBoot 3.x)+ MySQL 5.7 实打实跑起来的一套闭环系统。它解决的不是“如何写Hello World”,而是毕业答辩时评委最常问的三个问题:用户怎么登录?订单怎么不丢?数据怎么不乱?整套资源里,源码含完整前后端工程结构、开题报告明确写了“基于微信开放能力实现手机号一键授权”、论文里附了ER图与接口时序图、视频演示覆盖从首页滑动到支付回调再到管理端订单筛选的全过程。适合正在赶毕设 deadline 的计算机/软件工程本科生,也适合想快速复现一个“轻量级本地生活SaaS雏形”的初阶全栈开发者——它不追求高并发,但每一步都踩在微信生态和SpringBoot工程规范的边界上。
2. 技术选型为什么是微信小程序 + SpringBoot + MySQL:避开uniapp和Vue的典型误判
2.1 微信小程序原生开发:不是“不能用Vue”,而是“不该用Vue”
很多同学看到“微信小程序”第一反应是uniapp或Taro,但本项目坚持使用微信原生框架(WXML/WXSS/JS),原因很实际:
- 登录链路极简:直接调用
wx.login()+wx.getPhoneNumber()获取加密手机号,后端用WXBizDataCrypt解密,全程无第三方SDK依赖; - 支付对接零胶水:
wx.requestPayment()直接传prepay_id,SpringBoot侧只需调用微信统一下单API返回签名参数,不涉及H5跳转或OAuth2重定向; - 性能可控:首页商品列表用
wx:for渲染,配合wx:if控制规格弹窗显隐,首屏加载<1.2s(实测iPhone XR),而uniapp打包后体积多出1.8MB,对奶茶店老板用的千元机不友好。
提示:项目中所有WXML组件均未使用自定义组件(如
<van-button>),全部基于原生<button>+<view>构建,确保微信开发者工具基础库2.20.0+即可运行,避免因基础库版本差异导致bindtap失效等玄学问题。
2.2 SpringBoot 2.7.x:为什么不是3.x或2.6.x?
项目后端锁定SpringBoot 2.7.18(2023年10月GA版本),这是关键决策:
- MyBatis-Plus兼容性:本项目用MyBatis-Plus 3.5.3.1,若升级SpringBoot 3.x需同步升级MyBatis-Plus 4.x,而4.x废弃了
@TableId(type = IdType.AUTO)的自动递增逻辑,需手动改@TableId(type = IdType.INPUT)并维护ID生成器——但奶茶店订单ID必须全局唯一且可读(如DD202405170001),原方案用MySQLAUTO_INCREMENT+ 业务层拼接更稳妥; - 微信支付SDK适配:官方
weixin-java-pay4.4.0仅支持SpringBoot 2.7.x,若强行用2.6.x会触发RestTemplateBean注入冲突(No qualifying bean of type 'org.springframework.web.client.RestTemplate'); - JDK版本锁死:SpringBoot 2.7.x要求JDK 8u201+或JDK 11,而学校服务器普遍为CentOS 7 + JDK 8u191,无需额外升级环境。
2.3 MySQL 5.7:为什么不用8.0?
数据库选用MySQL 5.7.44(Windows版安装包已附在资源内),而非8.0,理由直击痛点:
- 全文索引分词兼容:商品搜索用
MATCH AGAINST,5.7默认使用ngram解析器,对“珍珠奶茶”“芋圆波霸”等中文词切分稳定;8.0虽支持innodb_ft_parser,但需额外配置ft_min_word_len=2且易受停用词表干扰; - 事务隔离级别明确:项目订单创建用
REPEATABLE READ,配合SELECT ... FOR UPDATE锁定库存,5.7的间隙锁(Gap Lock)行为与论文描述完全一致;8.0默认READ COMMITTED,需显式SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ,增加部署复杂度; - Navicat连接零配置:5.7默认
mysql_native_password认证插件,学生用Navicat 15直连无需改caching_sha2_password——这点省下3小时调试时间。
3. 源码结构拆解:从2048-小程序.zip到可运行的三步落地
3.1 小程序端:miniprogram/目录下的真实工程逻辑
解压2048-小程序.zip后,核心目录结构如下:
miniprogram/ ├── app.js # 全局App实例,含onLaunch中检查登录态 ├── app.json # 页面路径、tabBar、网络超时配置("networkTimeout": {"request": 10000}) ├── project.config.json # 开发者工具配置,含appid(需替换为你的) ├── pages/ │ ├── index/ # 首页:商品分类+瀑布流列表 │ │ ├── index.wxml # 商品卡片含<checkbox-group>控制规格选择 │ │ └── index.js # onPullDownRefresh触发商品刷新,调用/api/goods/list │ ├── order/ # 订单页:地址选择+支付按钮 │ │ └── order.js # wx.requestPayment()前校验库存,失败则toast提示"库存不足" │ └── admin/ # 管理端(需扫码进入):订单列表+状态筛选 └── utils/ └── request.js # 封装wx.request,自动添加token(从wx.getStorageSync('token')读取)关键代码块(pages/order/order.js支付逻辑):
// 调用微信支付前,先校验库存 wx.request({ url: 'https://your-domain.com/api/order/check-stock', method: 'POST', data: { goodsId: this.data.goodsId, count: this.data.count }, success: (res) => { if (res.data.code === 200) { // 库存充足,发起支付 wx.request({ url: 'https://your-domain.com/api/order/create', method: 'POST', data: { goodsId: this.data.goodsId, count: this.data.count }, success: (orderRes) => { if (orderRes.data.code === 200) { const payParams = orderRes.data.data; // 后端返回的timeStamp, nonceStr, package, signType, paySign wx.requestPayment({ timeStamp: payParams.timeStamp, nonceStr: payParams.nonceStr, package: payParams.package, signType: payParams.signType, paySign: payParams.paySign, success: () => wx.showToast({ title: '支付成功', icon: 'success' }), fail: (err) => wx.showToast({ title: '支付失败', icon: 'none' }) }); } } }); } else { wx.showToast({ title: res.data.msg || '库存不足', icon: 'none' }); } } });逻辑说明:此处采用“前端二次校验”而非纯后端校验,是因为微信支付回调有延迟(平均1.2s),若仅靠后端扣减库存,用户可能重复点击支付按钮导致超卖。前端校验虽非强一致,但配合后端SELECT ... FOR UPDATE已足够应对日均500单的奶茶店场景。
3.2 SpringBoot后端:springboot-server/中的核心模块
后端Maven结构清晰,pom.xml关键依赖:
<dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> <!-- 锁定版本,避免与SpringBoot 2.7.x冲突 --> </dependency> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-pay</artifactId> <version>4.4.0</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> <!-- 注意:驱动用8.0+,但数据库服务仍是5.7 --> </dependency> </dependencies>订单创建核心逻辑(OrderController.java):
@PostMapping("/create") public Result createOrder(@RequestBody OrderCreateDTO dto) { // 1. 查询商品信息(带库存) Goods goods = goodsService.getById(dto.getGoodsId()); if (goods.getStock() < dto.getCount()) { return Result.fail("库存不足"); } // 2. 扣减库存(行锁防超卖) goods.setStock(goods.getStock() - dto.getCount()); goodsService.updateById(goods); // MyBatis-Plus自动提交事务 // 3. 创建订单(状态=待支付) Order order = new Order(); order.setOrderId("DD" + DateUtil.format(new Date(), "yyyyMMdd") + String.format("%04d", orderMapper.selectCount(null) + 1)); order.setGoodsId(dto.getGoodsId()); order.setCount(dto.getCount()); order.setStatus(OrderStatus.WAIT_PAY.getCode()); orderMapper.insert(order); // 4. 调用微信统一下单API WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); request.setOutTradeNo(order.getOrderId()); request.setBody("奶茶订单"); request.setTotalFee((int) (goods.getPrice() * dto.getCount() * 100)); // 单位:分 request.setSpbillCreateIp("127.0.0.1"); // 此处应为真实IP,开发环境可填127.0.0.1 request.setNotifyUrl("https://your-domain.com/api/pay/callback"); try { WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(request); Map<String, String> payParams = new HashMap<>(); payParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); payParams.put("nonceStr", RandomUtil.randomString(32)); payParams.put("package", "prepay_id=" + result.getPrepayId()); payParams.put("signType", "RSA"); payParams.put("paySign", wxPayService.createOrderSign(payParams)); // RSA签名 return Result.success(payParams); } catch (WxPayException e) { log.error("微信统一下单失败", e); return Result.fail("支付初始化失败"); } }参数说明:
outTradeNo:必须全局唯一,项目用DDYYYYMMDDXXXX格式,避免UUID过长影响打印小票;totalFee:单位为分,强制转int防止浮点误差(如15.5 * 100 = 1550);notifyUrl:微信支付回调地址,需备案域名且HTTPS,本地调试可用ngrok或localtunnel;paySign:必须用RSA签名(非MD5),weixin-java-pay4.4.0默认启用RSA,若用错密钥会返回invalid sign。
3.3 数据库:sql/目录下的建表与初始化脚本
sql/schema.sql包含5张核心表:
| 表名 | 用途 | 关键字段 |
|---|---|---|
t_goods | 商品信息 | id,name,price,stock,category_id |
t_order | 订单主表 | order_id,goods_id,count,status,create_time |
t_user | 用户信息(微信openid) | openid,phone,nick_name,avatar_url |
t_category | 商品分类 | id,name,sort |
t_admin | 管理员账号 | username,password(BCrypt加密) |
初始化数据(sql/init-data.sql)中,t_goods插入12款常见奶茶(珍珠奶茶、茉莉奶绿等),t_category含“热饮”“冷饮”“加料”三类,确保首次启动后首页有数据可展示。特别注意t_order.status字段用tinyint存储枚举值(1=待支付,2=已支付,3=制作中,4=已完成),而非字符串,减少索引体积。
4. 避坑指南:这4个坑让我重装3次MySQL、改掉27处代码
4.1 现象:小程序登录后wx.getPhoneNumber()始终返回{"errMsg":"getPhoneNumber:fail"}
原因:
- 微信开发者工具未开启“调试基础库版本”,默认用最新版(如2.28.0),而
getPhoneNumber需基础库2.21.0+; - 后端
WXBizDataCrypt解密时,session_key已过期(微信session_key有效期2小时),但前端未重新wx.login()获取新code; project.config.json中appid未替换为自己的测试号,导致签名无效。
解决:
- 开发者工具右上角 → 详情 → 本地设置 → 勾选“调试基础库版本” → 选2.21.0;
app.js中onLaunch添加wx.checkSession()失败时强制wx.login();- 用 微信公众平台测试号 获取真实appid,并更新
project.config.json。
4.2 现象:SpringBoot启动报错Caused by: java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
原因:
pom.xml中spring-boot-starter-web版本与SpringBoot 2.7.x不匹配,常见于复制粘贴时用了3.x的starter;application.yml中spring.main.web-application-type: reactive被误设为reactive(本项目是Servlet容器)。
解决:- 删除
pom.xml中所有<version>标签,让SpringBoot BOM统一管理依赖版本; application.yml确认spring.main.web-application-type: servlet(默认值,可删除此行)。
4.3 现象:MySQL 5.7安装后Navicat连接报错Client does not support authentication protocol requested by server
原因:
- MySQL 5.7.44默认
plugin为caching_sha2_password,而Navicat 15以下版本仅支持mysql_native_password; root用户密码为空或简单密码,被安全策略拒绝。
解决:
- 以管理员身份运行CMD,进入MySQL bin目录:
cd C:\Program Files\MySQL\MySQL Server 5.7\bin mysql -u root -p- 执行以下SQL(将
your_password换成强密码):
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password'; FLUSH PRIVILEGES;- Navicat新建连接时,密码填
your_password,保存即可。
4.4 现象:支付成功后,/api/pay/callback收不到微信回调,订单状态卡在“待支付”
原因:
notifyUrl域名未在微信商户平台【产品中心→开发配置】中添加白名单;- SpringBoot未配置
server.ssl.key-store,导致HTTPS回调被微信拒绝(微信强制要求HTTPS); @RequestBody接收微信XML数据时,未用@RequestBody(required = false)且未处理空body。
解决:- 微信商户平台 → 产品中心 → 开发配置 → 支付授权目录添加
https://your-domain.com/api/pay/callback; - 本地调试用
ngrok http 8080生成HTTPS隧道,notifyUrl填https://xxx.ngrok.io/api/pay/callback; PayController.java中回调方法改为:
@PostMapping(value = "/callback", consumes = MediaType.APPLICATION_XML_VALUE) public String handleCallback(HttpServletRequest request, HttpServletResponse response) { try { String xmlData = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8); // 解析xmlData,验证签名,更新订单状态... return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>"; } catch (Exception e) { log.error("支付回调处理失败", e); return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[系统错误]]></return_msg></xml>"; } }5. 进阶技巧:把“能跑”变成“能交差”的3个硬核动作
5.1 让开题报告和论文真正匹配代码:补全这3处技术细节
很多同学的开题报告写着“采用JWT实现用户认证”,但代码里却是wx.login()+openid存库。要让答辩不被质疑,必须在文档中精准对应代码:
- 开题报告“关键技术”章节:将“用户认证”改为“基于微信OpenID的无状态会话管理”,并注明“不使用JWT,因小程序端存储token存在安全风险,改用服务端内存缓存+OpenID绑定用户”;
- 论文“系统设计”章节:在ER图中
user表增加openid字段(主键),删除token字段,在“数据库设计”小节强调“OpenID作为用户唯一标识,避免手机号收集合规风险”; - 视频演示脚本:在支付成功画面后,插入后台管理端订单列表刷新的镜头,并标注字幕:“订单状态由微信异步回调实时更新,非轮询”。
5.2 毕业答辩高频问题预演:准备这4个答案
| 问题 | 标准答案要点 | 代码佐证位置 |
|---|---|---|
| “订单超卖怎么解决?” | “前端二次校验+后端SELECT FOR UPDATE行锁,事务隔离级别REPEATABLE READ” | OrderController.java第22行goodsService.getById()后立即goodsService.updateById() |
| “微信登录为什么不用手机号?” | “初期仅需OpenID识别用户,手机号在支付环节通过getPhoneNumber授权获取,符合最小权限原则” | pages/index/index.js中wx.getPhoneNumber()调用位置 |
| “为什么用MyBatis-Plus不用JPA?” | “MyBatis-Plus对MySQL 5.7的分页插件支持更成熟,且XML映射便于调试复杂SQL” | mapper/OrderMapper.xml中<select id="selectPage">分页查询 |
| “管理端怎么防未授权访问?” | “admin页面路由加wx.navigateTo拦截,后端/admin/**接口校验session中adminToken” | utils/request.js中header: { 'Authorization': wx.getStorageSync('adminToken') } |
5.3 一键生成答辩PPT:用VS Code插件导出代码片段
别再手动截图代码!用VS Code安装插件CodeSnap,选中关键代码(如OrderController.createOrder()方法),右键→Copy as Image,直接粘贴到PPT。重点标出:
- 红框圈出
SELECT ... FOR UPDATE(证明防超卖); - 黄底高亮
wx.requestPayment()参数(证明支付链路完整); - 蓝线箭头指向
result.getPrepayId()(证明微信统一下单成功)。
这样做的PPT,评委一眼看懂技术深度,比堆砌架构图有效10倍。
从那以后我每次交毕设材料,都强制走一遍“微信开发者工具真机调试→Postman调后端接口→MySQL命令行查订单表”三连验证,哪怕只剩2小时答辩。因为奶茶店老板不会关心你用了什么设计模式,他只看手机扫完码,能不能立刻下单、付款、拿到小票——而这份资源,就是帮你把这三步钉死在代码里。希望帮到你。
本文还有配套的精品资源,点击获取