毕业设计实战:基于SpringBoot+Vue的鲜牛奶订购系统,从零到上线全流程拆解,附送避坑指南!

38 阅读13分钟

毕业设计实战:基于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. 下单支付模块(必做!难点)

核心流程

  1. 用户提交订单 → 检查库存 → 锁定库存(可选)
  2. 生成待支付订单 → 跳转支付页面
  3. 支付成功 → 扣减库存 → 更新订单状态
  4. 支付失败/超时 → 释放库存 → 取消订单

关键代码逻辑

// 下单逻辑(带事务)
@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(&#34;商品[&#34; + product.getName() + &#34;]库存不足&#34;);
        }
    }
    
    // 3. 扣减库存(使用乐观锁)
    for (OrderItemDTO item : items) {
        int rows = productMapper.reduceStock(item.getProductId(), item.getQuantity());
        if (rows == 0) {
            throw new RuntimeException(&#34;库存扣减失败,请重试&#34;);
        }
    }
    
    // 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(&#34;订单创建成功,请在15分钟内完成支付&#34;, order.getOrderNo());
}

2. 支付回调处理模块

支付流程

  1. 前端调用支付接口 → 生成支付参数
  2. 跳转到支付平台(微信/支付宝)或模拟支付页面
  3. 支付完成 → 支付平台回调通知系统
  4. 系统验证签名 → 更新订单状态

模拟支付实现(毕设可用):

// 模拟支付接口
@PostMapping(&#34;/pay&#34;)
public Result pay(@RequestBody PayDTO dto) {
    // 1. 查询订单
    Order order = orderService.getByOrderNo(dto.getOrderNo());
    if (order == null) {
        return Result.error(&#34;订单不存在&#34;);
    }
    
    // 2. 检查订单状态
    if (order.getStatus() != 0) {
        return Result.error(&#34;订单状态异常&#34;);
    }
    
    // 3. 检查支付金额
    if (order.getActualAmount().compareTo(dto.getAmount()) != 0) {
        return Result.error(&#34;支付金额不正确&#34;);
    }
    
    // 4. 模拟支付成功
    order.setStatus(1); // 已支付
    order.setPaymentType(dto.getPaymentType());
    order.setPaymentTime(new Date());
    orderService.updateById(order);
    
    // 5. 发送支付成功通知(可选)
    notificationService.sendPaymentSuccess(order.getUserId(), order);
    
    return Result.success(&#34;支付成功&#34;);
}

3. 库存预警模块(商家端)

功能要点

  • 实时显示库存情况
  • 设置库存预警阈值(如:库存