毕业设计实战:基于SpringBoot的电子产品销售系统设计与实现全攻略
在开发“基于SpringBoot的电子产品销售系统”毕业设计时,曾因“订单状态与库存管理脱节”踩过关键坑——初期未设计清晰的订单状态机和会员价联动机制,导致用户下单后库存未及时扣减、会员与非会员价格计算混乱、订单支付超时后库存未回滚,耗费4天重构订单管理模块、引入会员价机制和订单超时自动取消功能才解决问题📝。基于此次实战经验,本文精简拆解核心开发流程,附避坑要点与实操细节,为同类毕设提供可落地的实施参考。
一、需求分析:聚焦商品+订单双核心,避免功能冗余
部分同学易陷入“功能堆砌”误区,比如我曾耗时3天开发“电子产品参数对比”模块,最终因偏离“商品管理、购物车、订单处理、会员价”核心需求被导师要求删减。明确“商品发布→用户浏览→加入购物车→下单支付→库存扣减→会员价优惠”的业务闭环,是降低返工率的关键。
1. 核心角色与功能(精简版)
| 角色 | 核心功能 |
|---|---|
| 管理员 | 用户管理、产品类别管理、电子产品管理、留言板管理、订单管理、系统管理(通知公告、在线客服、轮播图) |
| 用户 | 注册登录、电子产品浏览/搜索/收藏/评论、购物车管理、下单支付、订单查询、在线客服、个人中心 |
2. 需求避坑要点
- 拒绝空想调研:邀请15名电子产品爱好者和5名商家模拟“用户浏览商品→加入购物车→会员价结算→下单支付→库存扣减→订单跟踪”完整流程,基于“用户需要知道会员优惠和订单状态”需求,增设“会员价标识”和“订单状态跟踪”模块,实用性远大于冗余的“参数对比”;
- 明确约束条件:提前规定“产品编号自动生成(格式:DZ+年月日+序号)”“会员价默认-1表示无会员价”“下单时扣减库存,支付失败自动回滚”“订单状态包括未支付、已支付、已发货、已完成、已取消”,为系统实现提供明确依据。
二、技术选型:稳定框架+会员价联动,新手可上手
前期曾尝试引入Redis缓存商品库存,因数据一致性难保证且学习成本高,调试耗时3天。最终确定“成熟框架+数据库事务”组合:
| 技术工具 | 选型理由 | 避坑提醒 |
|---|---|---|
| Spring Boot 2.x + MyBatis-Plus | 快速开发,简化配置,高效实现CRUD和业务逻辑,声明式事务管理方便 | 事务注解@Transactional记得在Service层添加;下单和库存扣减必须加事务 |
| Vue 2.x + ElementUI | 组件丰富,快速构建前后台界面,表格和表单组件好用 | 订单状态用标签展示;会员价用金色标识 |
| MySQL 5.7 | 存储用户、商品、订单、购物车等核心业务数据 | 金额字段用Decimal类型;事务要保证订单和库存一致性 |
| Thymeleaf(可选) | 服务端模板引擎,适合快速开发后台管理界面 | 毕设时间充裕可统一用Vue |
三、数据库设计:业务关联清晰,支撑商品-订单-会员闭环
数据库设计直接影响后续开发效率。前期因未设计“会员价字段”和“订单状态流转机制”,导致会员与非会员价格混乱、订单取消后库存未回滚。
1. 核心表结构(精选12张表)
- 管理员表(users):id、username、password(MD5加密)、role、addtime;
- 用户表(yonghu):id、zhanghao(账号)、mima(密码)、xingming(姓名)、nianling(年龄)、xingbie(性别)、shouji(手机)、youxiang(邮箱)、touxiang(头像)、money(余额)、vip(是否会员)、addtime;
- 产品类别表(chanpinleibie):id、chanpinleibie(产品类别)、addtime;
- 电子产品表(dianzichanpin):id、chanpinbianhao(产品编号)、chanpinmingcheng(产品名称)、chanpinleibie(产品类别)、pinpai(品牌)、guige(规格)、fengmian(封面)、shangjiariqi(上架日期)、chanpinjieshao(产品介绍)、onelimittimes(单限)、alllimittimes(库存)、thumbsupnum(赞)、crazilynum(踩)、clicktime、clicknum、price(价格)、vipprice(会员价)、addtime;
- 购物车表(cart):id、tablename(商品表名)、userid(用户id)、goodid(商品id)、goodname(商品名称)、picture(图片)、buynumber(购买数量)、price(单价)、discountprice(会员价)、addtime;
- 订单表(orders):id、orderid(订单编号)、tablename(商品表名)、userid(用户id)、goodid(商品id)、goodname(商品名称)、picture(图片)、buynumber(购买数量)、price(价格)、total(总价格)、type(支付类型)、status(订单状态)、address(地址)、tel(电话)、consignee(收货人)、remark(备注)、logistics(物流)、addtime;
- 地址表(address):id、userid(用户id)、address(地址)、name(收货人)、phone(电话)、isdefault(是否默认地址)、addtime;
- 收藏表(shoucang):id、userid、refid、tablename、name、picture、type(收藏类型)、addtime;
- 留言板表(liuyanban):id、userid、username、avatarurl、content、cpicture、reply、rpicture、addtime;
- 在线客服表(zaixiankefu):id、userid、adminid、ask(提问)、reply(回复)、isreply(是否回复)、addtime;
- 通知公告表(tongzhigonggao):id、title、introduction、picture、content、addtime;
- token表(token):id、userid、username、tablename、role、token、addtime、expiratedtime。
2. 关键业务SQL示例
示例SQL(查询用户订单及商品会员价):
-- 查询用户的订单记录,包含商品会员价信息
SELECT
o.*,
d.price as normal_price,
d.vipprice as vip_price,
CASE WHEN u.vip = '是' THEN d.vipprice ELSE d.price END as actual_price
FROM orders o
LEFT JOIN dianzichanpin d ON o.goodid = d.id
LEFT JOIN yonghu u ON o.userid = u.id
WHERE o.userid = #{userId}
ORDER BY o.addtime DESC
关键避坑:会员价字段默认-1表示无会员价;下单时根据用户会员状态计算实际价格;订单超时需自动取消并回滚库存。
四、核心功能实现:8大模块满足答辩需求
无需复杂功能,优先完成以下8个核心模块,其中会员价计算与库存联动是答辩重点。
1. 用户管理(基础模块)
- 核心逻辑:用户注册登录、个人信息维护、余额管理、会员状态管理;
- 页面设计:注册登录界面;个人中心显示头像、姓名、余额、会员标识;
- 代码要点(用户注册与会员判断):
public void addYonghu(Yonghu user) {
// 校验账号是否重复
LambdaQueryWrapper<Yonghu> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Yonghu::getZhanghao, user.getZhanghao());
if (yonghuMapper.selectCount(wrapper) > 0) {
throw new RuntimeException("账号已存在");
}
user.setMoney(0f);
user.setVip("否");
user.setAddtime(new Date());
yonghuMapper.insert(user);
}
// 判断用户是否为会员
public boolean isVip(Long userId) {
Yonghu user = yonghuMapper.selectById(userId);
return "是".equals(user.getVip());
}
2. 电子产品管理(核心资源模块)
- 核心逻辑:管理员发布商品(名称、类别、品牌、规格、价格、会员价、库存)→用户浏览、搜索、收藏、评论;
- 页面设计:商品卡片式展示,显示名称、图片、价格、会员价(金色标识)、库存;详情页展示完整信息;
- 代码要点(商品发布与库存管理):
@Transactional
public void addDianzichanpin(Dianzichanpin product) {
// 生成商品编号
String bianhao = "DZ" + new SimpleDateFormat("yyyyMMdd").format(new Date())
+ String.format("%04d", new Random().nextInt(10000));
product.setChanpinbianhao(bianhao);
product.setThumbsupnum(0);
product.setCrazilynum(0);
product.setClicknum(0);
product.setAddtime(new Date());
dianzichanpinMapper.insert(product);
log.info("管理员发布了商品:{}", product.getChanpinmingcheng());
}
// 库存扣减
public void reduceStock(Long productId, int quantity) {
Dianzichanpin product = dianzichanpinMapper.selectById(productId);
if (product.getAlllimittimes() < quantity) {
throw new RuntimeException("库存不足");
}
product.setAlllimittimes(product.getAlllimittimes() - quantity);
dianzichanpinMapper.updateById(product);
}
// 库存回滚(订单取消时)
public void rollbackStock(Long productId, int quantity) {
Dianzichanpin product = dianzichanpinMapper.selectById(productId);
product.setAlllimittimes(product.getAlllimittimes() + quantity);
dianzichanpinMapper.updateById(product);
}
3. 购物车管理(交易准备模块)
- 核心逻辑:用户将商品加入购物车→根据会员状态显示会员价→修改数量;
- 页面设计:购物车列表显示商品名称、图片、单价(会员价标识)、数量、总价;
- 代码要点(购物车添加与价格计算):
public void addCart(Cart cart, Long userId) {
// 校验是否已存在
LambdaQueryWrapper<Cart> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(Cart::getGoodid, cart.getGoodid())
.eq(Cart::getUserid, userId);
Cart existCart = cartMapper.selectOne(wrapper);
// 获取商品价格(根据会员状态)
Dianzichanpin product = dianzichanpinMapper.selectById(cart.getGoodid());
boolean isVip = isVip(userId);
float actualPrice = getActualPrice(product, isVip);
cart.setPrice(actualPrice);
cart.setDiscountprice(isVip ? product.getVipprice() : -1f);
if (existCart != null) {
existCart.setBuynumber(existCart.getBuynumber() + cart.getBuynumber());
cartMapper.updateById(existCart);
} else {
cart.setUserid(userId);
cart.setAddtime(new Date());
cartMapper.insert(cart);
}
}
// 获取实际价格(会员价或原价)
private float getActualPrice(Dianzichanpin product, boolean isVip) {
if (isVip && product.getVipprice() != null && product.getVipprice() > 0) {
return product.getVipprice();
}
return product.getPrice();
}
4. 订单管理(核心业务流程)
- 核心逻辑:用户确认下单→创建订单→扣减库存→支付→发货→确认收货;
- 页面设计:订单列表显示订单编号、商品名称、数量、总价、状态;支持支付、取消、确认收货;
- 代码要点(订单创建与会员价联动):
@Transactional
public Orders createOrder(Long userId, List<Cart> cartItems, Address address) {
// 1. 生成订单编号
String orderId = "DD" + System.currentTimeMillis();
Orders mainOrder = null;
// 2. 获取用户会员状态
boolean isVip = isVip(userId);
for (Cart cart : cartItems) {
// 3. 获取商品及价格
Dianzichanpin product = dianzichanpinMapper.selectById(cart.getGoodid());
float actualPrice = getActualPrice(product, isVip);
// 4. 校验库存
if (product.getAlllimittimes() < cart.getBuynumber()) {
throw new RuntimeException("商品 " + product.getChanpinmingcheng() + " 库存不足");
}
// 5. 创建订单项
Orders order = new Orders();
order.setOrderid(orderId);
order.setUserid(userId);
order.setGoodid(cart.getGoodid());
order.setGoodname(cart.getGoodname());
order.setPicture(cart.getPicture());
order.setBuynumber(cart.getBuynumber());
order.setPrice(actualPrice);
order.setTotal(actualPrice * cart.getBuynumber());
order.setStatus("未支付");
order.setAddress(address.getAddress());
order.setTel(address.getPhone());
order.setConsignee(address.getName());
order.setAddtime(new Date());
ordersMapper.insert(order);
// 6. 扣减库存
reduceStock(cart.getGoodid(), cart.getBuynumber());
// 7. 删除购物车记录
cartMapper.deleteById(cart.getId());
if (mainOrder == null) mainOrder = order;
}
// 8. 设置订单超时自动取消(定时任务)
scheduleOrderTimeout(orderId);
log.info("用户 {} 创建订单 {}", userId, orderId);
return mainOrder;
}
// 订单支付
@Transactional
public void payOrder(String orderId) {
// 更新订单状态
LambdaUpdateWrapper<Orders> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(Orders::getOrderid, orderId)
.eq(Orders::getStatus, "未支付")
.set(Orders::getStatus, "已支付");
int updated = ordersMapper.update(null, wrapper);
if (updated == 0) {
throw new RuntimeException("订单状态异常,请刷新后重试");
}
log.info("订单 {} 支付成功", orderId);
}
// 订单取消(超时或用户主动取消)
@Transactional
public void cancelOrder(String orderId) {
// 1. 查询订单项
List<Orders> orderList = ordersMapper.selectList(
new LambdaQueryWrapper<Orders>().eq(Orders::getOrderid, orderId)
);
// 2. 回滚库存
for (Orders order : orderList) {
if ("已支付".equals(order.getStatus())) {
rollbackStock(order.getGoodid(), order.getBuynumber());
}
}
// 3. 更新订单状态
LambdaUpdateWrapper<Orders> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(Orders::getOrderid, orderId)
.in(Orders::getStatus, "未支付", "已支付")
.set(Orders::getStatus, "已取消");
ordersMapper.update(null, wrapper);
log.info("订单 {} 已取消", orderId);
}
5. 订单超时自动取消(定时任务)
@Component
public class OrderTimeoutTask {
@Scheduled(cron = "0 */5 * * * ?") // 每5分钟执行一次
@Transactional
public void cancelTimeoutOrders() {
// 查询超过30分钟未支付的订单
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.MINUTE, -30);
Date timeout = calendar.getTime();
List<Orders> timeoutOrders = ordersMapper.selectList(
new LambdaQueryWrapper<Orders>()
.eq(Orders::getStatus, "未支付")
.lt(Orders::getAddtime, timeout)
.groupBy(Orders::getOrderid)
);
Set<String> orderIds = timeoutOrders.stream()
.map(Orders::getOrderid)
.collect(Collectors.toSet());
for (String orderId : orderIds) {
cancelOrder(orderId);
log.info("订单 {} 超时自动取消", orderId);
}
}
}
6. 地址管理(收货模块)
- 核心逻辑:用户维护收货地址(收货人、电话、地址),支持设置默认地址;
- 页面设计:地址列表显示收货人、电话、地址、默认标识;支持增删改查;
- 代码要点:设置默认地址时取消其他默认地址。
7. 留言板/在线客服(互动模块)
- 核心逻辑:用户留言反馈/在线咨询→管理员回复;
- 页面设计:留言板显示留言内容、图片、回复;在线咨询支持问答;
- 代码要点:支持留言图片上传;客服回复状态跟踪。
五、电子产品销售特色功能设计(关键加分项)
电子产品销售系统的核心在于“商品-购物车-订单-库存全流程联动+会员价优惠”,以下是实测有效的设计方案:
1. 商品-购物车-订单全流程追溯
| 环节 | 记录内容 | 可追溯信息 |
|---|---|---|
| 商品发布 | 商品编号、名称、类别、品牌、价格、会员价、库存 | 什么商品、多少钱、会员价多少 |
| 购物车 | 商品名称、数量、单价(会员价标识)、总价 | 加了什么、加了多少 |
| 订单创建 | 订单编号、商品信息、收货地址、订单状态 | 什么时候买的、发到哪、什么状态 |
| 库存扣减 | 商品ID、扣减数量、剩余库存 | 扣了多少、还剩多少 |
| 订单支付 | 支付时间、支付金额 | 付了多少钱、什么时候付的 |
2. 会员价计算机制
// 会员价计算工具类
public class PriceCalculator {
// 获取商品实际价格
public static float getActualPrice(Dianzichanpin product, boolean isVip) {
if (isVip && product.getVipprice() != null && product.getVipprice() > 0) {
return product.getVipprice();
}
return product.getPrice();
}
// 计算订单总价(批量)
public static float calculateTotal(List<Cart> cartItems, boolean isVip) {
float total = 0;
for (Cart item : cartItems) {
Dianzichanpin product = getProduct(item.getGoodid());
float price = getActualPrice(product, isVip);
total += price * item.getBuynumber();
}
return total;
}
}
3. 库存预警机制
// 定时任务:检查库存低于阈值的商品
@Component
public class StockAlertTask {
@Scheduled(cron = "0 0 9 * * ?") // 每天上午9点执行
public void checkStock() {
List<Dianzichanpin> list = dianzichanpinMapper.selectList(null);
for (Dianzichanpin product : list) {
if (product.getAlllimittimes() <= 5) {
log.warn("商品 {} 库存不足,当前库存:{}",
product.getChanpinmingcheng(), product.getAlllimittimes());
// 可发送通知给管理员
}
}
}
}
4. 热门商品推荐
-- 基于销量、收藏量、点击量推荐热门商品
SELECT
d.*,
COUNT(DISTINCT o.id) as order_count,
COUNT(DISTINCT s.id) as collect_count,
(COUNT(DISTINCT o.id) * 0.5 + COUNT(DISTINCT s.id) * 0.3 + d.clicknum * 0.2) as hot_score
FROM dianzichanpin d
LEFT JOIN orders o ON d.id = o.goodid AND o.status = '已完成'
LEFT JOIN shoucang s ON d.id = s.refid AND s.type = '1'
GROUP BY d.id
ORDER BY hot_score DESC
LIMIT 10
六、测试与答辩:流程演示为主,突出电商购物闭环
1. 核心测试用例
| 测试场景 | 操作步骤 | 预期结果 |
|---|---|---|
| 商品发布全流程 | 管理员发布商品(含会员价)→用户查看 | 商品信息正确显示;会员价金色标识 |
| 会员价测试 | 会员用户与非会员用户查看同一商品 | 会员看到会员价,非会员看到原价 |
| 购物车流程 | 用户添加商品到购物车→价格计算 | 购物车显示正确价格(会员价/原价) |
| 下单支付流程 | 用户下单→支付→库存扣减 | 订单生成;库存减少;订单状态更新 |
| 订单取消流程 | 用户取消订单→库存回滚 | 订单状态更新为已取消;库存恢复 |
| 超时自动取消 | 订单30分钟未支付 | 订单自动取消;库存回滚 |
2. 答辩准备技巧
- 演示流程:分角色演示(管理员端 + 用户端)→ 管理员发布电子产品(设置会员价)→ 用户A注册为普通用户 → 用户B注册为会员 → 对比查看商品价格差异 → 用户B将商品加入购物车 → 用户B下单 → 支付 → 库存扣减 → 管理员发货 → 用户B确认收货 → 订单完成 → 展示完整的商品-购物车-订单-库存-会员价管理闭环;
- 业务讲解:准备一页PPT展示系统功能结构图(图4-2),说明每个模块的作用和角色定位;
- 技术亮点:重点讲解会员价计算机制、下单与库存扣减的事务一致性、订单超时自动取消;
- 突出问题解决:讲清“如何保证会员与非会员价格正确”(根据用户会员状态动态计算)、“如何保证库存不超卖”(下单时扣减库存+事务)、“订单超时如何自动取消”(定时任务+状态检测);提前预判“为什么要设计会员价字段”,回答“吸引会员用户,提高用户粘性和复购率”。
结语
本文核心是“聚焦商品-订单-会员核心业务、实现电商购物闭环、设计完整的电子产品销售系统”。毕设无需复杂系统,把商品管理+购物车+订单管理+会员价的业务逻辑讲透、实现一个可运行的电子产品销售系统、展示完整的购物闭环,即可成为答辩亮点。
若需完整项目源码(带详细注释)、测试数据SQL脚本、订单超时取消完整代码,可在评论区留言“SpringBoot电子产品销售系统”获取;开发中遇问题(如事务一致性、会员价计算、库存并发控制),也可留言咨询~ 祝毕设顺利!🎉