毕业设计实战:基于SpringBoot+Vue的鲜牛奶订购系统,从零到上线全流程拆解,附送避坑指南!
谁懂啊!当初做鲜牛奶订购系统毕设时,光“订单并发”和“库存扣减”问题就折腾了我一周——一开始没加数据库事务锁,结果同一瓶牛奶卖给了两个人,导师直接让我“重写库存管理逻辑”😫 今天把从需求分析到功能实现的全流程经验分享出来,跟着做就能轻松搞定毕设!
一、先搞懂“鲜牛奶订购系统要做什么”!需求分析是关键
刚开始我跳过需求分析就写代码,花两周做了个“智能推荐算法”,结果导师一句“核心是商家管理、库存控制、订单处理,不是推荐算法”直接打回重改!
1. 核心用户&功能拆解(实战总结版)
鲜牛奶订购系统有三类核心用户:管理员、商家、消费者,功能要区分清楚:
-
管理员端(系统管理):
- 商家管理:审核商家入驻、管理商家信息(营业执照、星级评定)、禁用违规商家
- 用户管理:管理消费者账号、重置密码、查看消费记录
- 公告管理:发布系统通知、管理公告内容
- 数据统计:销售额统计、热销商品分析、用户活跃度
-
商家端(商品管理):
- 商品管理:上架商品(名称、图片、价格、库存)、设置上下架、修改商品信息
- 库存管理:实时查看库存、设置库存预警、补货管理
- 订单管理:处理消费者订单(接单、发货、取消)、查看订单详情
- 评价管理:回复消费者评价、查看商品评分
- 数据统计:店铺销售分析、热销时段统计
-
消费者端(购物消费):
- 商品浏览:查看商家列表、浏览商品、按分类筛选
- 购物车:添加商品到购物车、修改数量、批量结算
- 下单支付:选择收货地址、确认订单、在线支付
- 订单管理:查看订单状态(待支付/待发货/已发货/已完成)、申请退款
- 个人中心:管理收货地址、查看余额、修改个人信息
2. 需求分析避坑指南(血泪教训!)
- 别一个人闷头想!找同学测试提意见:有同学说“想看到牛奶的保质期”,我才加了“生产日期/保质期”字段,比加“智能推荐”实用多了
- 一定要画用例图!用DrawIO画“消费者-下单支付”“商家-库存管理”等核心用例
- 写需求规格文档!约束条件要写清楚:“库存不能为负数”“订单15分钟未支付自动取消”“退款需在收货前申请”
3. 可行性分析要专业
导师最爱问“可行吗”,从3个角度回答:
- 技术可行:SpringBoot+Vue+MySQL都是成熟技术,资料丰富
- 经济可行:开发工具全免费,服务器可用学生优惠
- 操作可行:界面参考美团/饿了么,用户上手快
二、技术选型别追新!稳定最重要
刚开始我用微服务+Redis+MongoDB,结果配置复杂,本地都跑不起来😫 后来换成SpringBoot 2.7+Vue2+MySQL 8.0,真香!
1. 技术栈对比(附避坑提醒)
| 技术工具 | 为什么选它 | 避坑提醒! |
|---|---|---|
| SpringBoot 2.7 | 配置简单,内置Tomcat,生态完善 | 别用3.0!部分依赖不稳定 |
| Vue 2 | 生态成熟,Element UI组件丰富 | 别用Vue 3组合式API!增加复杂度 |
| Element UI | 组件齐全,开发效率高 | 按需引入,避免打包过大 |
| MySQL 8.0 | 支持事务,保证数据一致性 | utf8mb4编码必须设! |
| Redis(可选) | 缓存热点商品,提升性能 | 别强求!不加也能完成毕设 |
2. 开发环境搭建
# 后端
spring init --dependencies=web,mybatis,mysql,jdbc,lombok milk-order
# 前端
vue create milk-order-frontend
cd milk-order-frontend
vue add element
npm install axios vue-router vuex
3. 架构图要画!答辩加分
用DrawIO画前后端分离架构图:
- 前端:Vue + Element UI + Axios + Vue Router
- 后端:SpringBoot + MyBatis + MySQL
- 存储:MySQL(业务数据)+ Redis(缓存)
- 部署:Nginx(反向代理)+ Docker(容器化)
三、数据库设计:库存管理是核心
这部分是系统的核心,我当初库存表设计不合理,并发下单就出问题。
1. 核心实体&ER图
核心表设计:
- 用户表(user):id、用户名、手机号、密码、头像、余额
- 商家表(merchant):id、商家名、联系方式、营业执照、星级、状态
- 商品表(product):id、商品名、图片、价格、库存、商家ID、保质期
- 购物车表(cart):id、用户ID、商品ID、数量、添加时间
- 订单表(order):id、订单号、用户ID、总金额、状态、创建时间
- 订单详情表(order_detail):id、订单ID、商品ID、数量、单价
- 收货地址表(address):id、用户ID、收货人、电话、地址、是否默认
- 评价表(comment):id、订单ID、用户ID、商品ID、评分、内容、时间
2. 建表SQL示例(关键表)
-- 商品表(核心业务表)
CREATE TABLE `product` (
`id` int NOT NULL AUTO_INCREMENT,
`merchant_id` int NOT NULL COMMENT '商家ID',
`name` varchar(100) NOT NULL COMMENT '商品名称',
`image` varchar(200) DEFAULT NULL COMMENT '商品图片',
`price` decimal(10,2) NOT NULL COMMENT '单价',
`stock` int NOT NULL DEFAULT 0 COMMENT '库存',
`shelf_life` int DEFAULT NULL COMMENT '保质期(天)',
`production_date` date DEFAULT NULL COMMENT '生产日期',
`status` int DEFAULT 1 COMMENT '状态(1-上架,0-下架)',
`sold_count` int DEFAULT 0 COMMENT '已售数量',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_merchant` (`merchant_id`),
KEY `idx_status` (`status`),
CONSTRAINT `fk_product_merchant` FOREIGN KEY (`merchant_id`) REFERENCES `merchant` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 订单表(业务核心)
CREATE TABLE `order` (
`id` int NOT NULL AUTO_INCREMENT,
`order_no` varchar(50) NOT NULL COMMENT '订单号',
`user_id` int NOT NULL COMMENT '用户ID',
`merchant_id` int NOT NULL COMMENT '商家ID',
`address_id` int NOT NULL COMMENT '收货地址ID',
`total_amount` decimal(10,2) NOT NULL COMMENT '订单总金额',
`actual_amount` decimal(10,2) NOT NULL COMMENT '实付金额',
`status` int DEFAULT 0 COMMENT '状态(0-待支付,1-已支付,2-已发货,3-已完成,4-已取消,5-已退款)',
`payment_type` int DEFAULT NULL COMMENT '支付类型(1-微信,2-支付宝,3-余额)',
`payment_time` datetime DEFAULT NULL COMMENT '支付时间',
`delivery_time` datetime DEFAULT NULL COMMENT '发货时间',
`complete_time` datetime DEFAULT NULL COMMENT '完成时间',
`cancel_time` datetime DEFAULT NULL COMMENT '取消时间',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_no` (`order_no`),
KEY `idx_user` (`user_id`),
KEY `idx_merchant` (`merchant_id`),
KEY `idx_status` (`status`),
KEY `idx_create_time` (`create_time`),
CONSTRAINT `fk_order_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `fk_order_merchant` FOREIGN KEY (`merchant_id`) REFERENCES `merchant` (`id`),
CONSTRAINT `fk_order_address` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 订单详情表
CREATE TABLE `order_detail` (
`id` int NOT NULL AUTO_INCREMENT,
`order_id` int NOT NULL COMMENT '订单ID',
`product_id` int NOT NULL COMMENT '商品ID',
`product_name` varchar(100) NOT NULL COMMENT '商品名称(快照)',
`product_image` varchar(200) DEFAULT NULL COMMENT '商品图片(快照)',
`price` decimal(10,2) NOT NULL COMMENT '单价(快照)',
`quantity` int NOT NULL COMMENT '购买数量',
`subtotal` decimal(10,2) NOT NULL COMMENT '小计金额',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_order` (`order_id`),
KEY `idx_product` (`product_id`),
CONSTRAINT `fk_detail_order` FOREIGN KEY (`order_id`) REFERENCES `order` (`id`),
CONSTRAINT `fk_detail_product` FOREIGN KEY (`product_id`) REFERENCES `product` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 库存扣减方案(难点!)
方案一(简单版):UPDATE时检查库存
UPDATE product
SET stock = stock - #{quantity},
sold_count = sold_count + #{quantity}
WHERE id = #{productId}
AND stock >= #{quantity}
方案二(推荐版):乐观锁+版本号
-- 商品表增加version字段
ALTER TABLE product ADD COLUMN `version` int DEFAULT 0;
-- 更新时检查版本
UPDATE product
SET stock = stock - #{quantity},
version = version + 1
WHERE id = #{productId}
AND stock >= #{quantity}
AND version = #{oldVersion}
方案三(高并发版):Redis预减库存 + 消息队列异步扣减
四、功能实现:核心模块详解
1. 下单支付模块(必做!难点)
核心流程:
- 用户提交订单 → 检查库存 → 锁定库存(可选)
- 生成待支付订单 → 跳转支付页面
- 支付成功 → 扣减库存 → 更新订单状态
- 支付失败/超时 → 释放库存 → 取消订单
关键代码逻辑:
// 下单逻辑(带事务)
@Transactional
public Result createOrder(OrderCreateDTO dto) {
// 1. 检查收货地址
Address address = addressService.getById(dto.getAddressId());
if (address == null || !address.getUserId().equals(getCurrentUserId())) {
return Result.error("收货地址无效");
}
// 2. 检查商品库存(加锁防止超卖)
List items = dto.getItems();
for (OrderItemDTO item : items) {
Product product = productService.getById(item.getProductId());
if (product.getStock() < item.getQuantity()) {
return Result.error("商品[" + product.getName() + "]库存不足");
}
}
// 3. 扣减库存(使用乐观锁)
for (OrderItemDTO item : items) {
int rows = productMapper.reduceStock(item.getProductId(), item.getQuantity());
if (rows == 0) {
throw new RuntimeException("库存扣减失败,请重试");
}
}
// 4. 生成订单
Order order = new Order();
order.setOrderNo(generateOrderNo());
order.setUserId(getCurrentUserId());
order.setAddressId(dto.getAddressId());
order.setTotalAmount(calculateTotalAmount(items));
order.setActualAmount(order.getTotalAmount()); // 实际业务可能有优惠
order.setStatus(0); // 待支付
orderMapper.insert(order);
// 5. 生成订单详情
for (OrderItemDTO item : items) {
Product product = productService.getById(item.getProductId());
OrderDetail detail = new OrderDetail();
detail.setOrderId(order.getId());
detail.setProductId(item.getProductId());
detail.setProductName(product.getName());
detail.setProductImage(product.getImage());
detail.setPrice(product.getPrice());
detail.setQuantity(item.getQuantity());
detail.setSubtotal(product.getPrice().multiply(new BigDecimal(item.getQuantity())));
orderDetailMapper.insert(detail);
}
return Result.success("订单创建成功,请在15分钟内完成支付", order.getOrderNo());
}
2. 支付回调处理模块
支付流程:
- 前端调用支付接口 → 生成支付参数
- 跳转到支付平台(微信/支付宝)或模拟支付页面
- 支付完成 → 支付平台回调通知系统
- 系统验证签名 → 更新订单状态
模拟支付实现(毕设可用):
// 模拟支付接口
@PostMapping("/pay")
public Result pay(@RequestBody PayDTO dto) {
// 1. 查询订单
Order order = orderService.getByOrderNo(dto.getOrderNo());
if (order == null) {
return Result.error("订单不存在");
}
// 2. 检查订单状态
if (order.getStatus() != 0) {
return Result.error("订单状态异常");
}
// 3. 检查支付金额
if (order.getActualAmount().compareTo(dto.getAmount()) != 0) {
return Result.error("支付金额不正确");
}
// 4. 模拟支付成功
order.setStatus(1); // 已支付
order.setPaymentType(dto.getPaymentType());
order.setPaymentTime(new Date());
orderService.updateById(order);
// 5. 发送支付成功通知(可选)
notificationService.sendPaymentSuccess(order.getUserId(), order);
return Result.success("支付成功");
}
3. 库存预警模块(商家端)
功能要点:
- 实时显示库存情况
- 设置库存预警阈值(如:库存