基于springboot+vue+mysql「校园二手教材循环交易」小程序,三端全跑通

我做了一个「校园二手教材循环交易」平台,三端全跑通,聊聊那些答辩老师一定会问的点

关键词:校园二手交易平台 / SpringBoot3 小程序 / 微信小程序二手书 / 漂流积分 / 设计源码

每年六月,宿舍楼下都会出现一个奇观:一摞摞教材被塞进纸箱,旁边立一块纸板,写着"5 元一本随便挑"。而到了九月,同样的书又被新生以原价七八十的价格重新买回来。

同一本书,在同一个校园里,一年之内完成了"贱卖---回收"的完整循环,中间没有任何人赚到差价,只有纸张和钱各自被浪费了一次。

这个现象背后其实藏着一个很标准的软件选题------校园二手教材与闲置物品交易平台。它足够贴近生活(老师一听就懂)、业务逻辑足够完整(登录、发布、审核、订单状态机、评价、统计一应俱全),而且比烂大街的"图书管理系统"有意思得多。

我把这个项目完整做了一遍,取名 「拾光流转」 ,三端全套跑通。


一、先说结论:这个项目是什么规模

这个项目是完整的三端架构:

端 技术栈 规模
后端 server SpringBoot 3.2.5 + Java 17 + MyBatis-Plus 3.5.5 + MySQL + Hutool(JWT / MD5)+ Lombok 2275 行,56 个 REST 接口
管理后台 admin-web Vue 3 + Vite + Element Plus + ECharts + Axios 1143 行,10 个页面
小程序 miniprogram 微信原生小程序(无框架,直接用 WXML/WXSS) 2786 行,14 个页面

数据库 9 张表:user / category / product / favorite / orders / message / points_log / review / notice,附带一份 init.sql,一键建库建表并灌入种子数据------4 个测试账号 + 6 个分类 + 7 件商品 + 公告 + 积分流水。

这点很重要:很多毕设交上去,老师第一步就是"能不能跑起来"。如果数据库要手工建表、数据要自己填,第一印象就崩了。


二、设计决策 1:为什么不接微信授权登录

这是我最想聊的一点。

几乎所有校园二手平台的需求文档里都写着"微信一键登录"。听起来很香,但实操时你会撞上两堵墙:

  1. 需要企业主体的 AppID + AppSecret 。个人主体的测试号拿不到 code2session 的完整权限,openid 拿不到就是死循环。
  2. 域名没备案 ,wx.login 一超时,整个演示直接卡在登录页。

所以这个项目用账号密码登录,注册即送 30 积分 。JWT 自己签发、自己校验,AuthInterceptor 拦 /api/admin/** 和需要登录的用户接口,token 里塞 userId 和 role,管理员和普通用户走同一套认证。

代价是"没那么潮",收益是:任何人 clone 下来,npm 和 MySQL 装好,十分钟之内一定能登录进去看到东西。

如果你确实要接微信登录,AuthController 里预留了扩展位------只要把 openid 写进 user 表并加一个 code2session 的调用,其余逻辑一行不用改。这是我在设计表结构时就留好的口子。


三、设计决策 2:订单状态机,别用 if-else 堆

二手交易和普通电商最大的不同是:没有物流。

校内面交、宿舍楼下自提,意味着整个履约链路被压缩成"付款 → 到点取货 → 确认收货"。所以状态机只有四个状态:

复制代码
0 待付款  →  1 待自提  →  2 已完成
                 ↓
              3 已取消

但"简单"不等于"可以随便写"。这个项目里我把状态流转全部收在 OrderService 一个类里,每个动作一个方法,并且每个方法都做三重校验:

  • getOwned(orderId, userId, true) ------ 校验订单归属,防止别人改你的订单
  • 状态前置判断 ------ if (order.getStatus() != 1) throw new BizException("订单还未支付或已完成")
  • @Transactional(rollbackFor = Exception.class) ------ 下单失败不留下半条脏数据

有个细节值得单独说:取消订单时商品要重新上架。

java 复制代码
order.setStatus(3);
Product product = productMapper.selectById(order.getProductId());
if (product != null && product.getStatus() == 1) {
    product.setStatus(0);   // 从"已预定"回到"在售"
    productMapper.updateById(product);
}

这段逻辑看起来平淡,但答辩时老师最爱问:"如果用户下单后不付款,商品就永远锁死了吗? "------不,取消即释放,而且积分兑换的单子取消后积分会原路退还(买家加回、卖家扣回),这是 OrderService.cancel 里另一段容易漏掉的对称逻辑。


四、设计决策 3:ISBN 识别,10 本书的内置书库反而是加分项

需求文档里写着"集成 ISBN 扫码识别 API"。真接了会有两个问题:

  • 第三方书籍 API 基本都要付费或限次,答辩演示时额度用完就尴尬
  • 网络不通时,发布页直接变砖

我的做法是在 CommonController 里内置了一个 10 本书的本地书库 ,用 HashMap 存 ISBN → [书名, 出版社, 定价]:

java 复制代码
ISBN_DB.put("9787040396638", new String[]{"高等数学(第七版)上册 同济大学", "高等教育出版社", "44.20"});
ISBN_DB.put("9787302147510", new String[]{"数据结构(C语言版)严蔚敏", "清华大学出版社", "35.00"});
// ... 共 10 本,覆盖高数、线代、概率论、数据结构、计网、大物、Java、CSAPP、四级真题

查不到就返回 404 + "未找到该ISBN对应书籍,请手动填写",前端自动降级成手动输入。

为什么说这反而是加分项? 因为老师问"你这个 ISBN 是调真实 API 的吗",你答:"是本地书库模拟,接口层做了防腐设计,换真实 API 只需要替换 isbn() 这一个方法体,前端和数据库完全不用动。"------这个回答的分量,远比"我在网上找了个免费 API"要重。

它证明你理解接口抽象 ,而不是只会抄调用。


五、这个项目真正的差异点:漂流积分

如果只是"发布---浏览---下单---评价",那它和任何电商模板没有区别。所以我在现金支付之外做了第二套支付体系:漂流积分。

规则设计得很克制,三条:

行为 积分变化
注册 +30
商品首次审核通过 卖家 +10
订单完成 买卖双方各 +20
积分兑换下单 买家扣、卖家收;订单取消则原路退还

关键在于积分是走账的,不是写死的 。每次变动都往 points_log 插一条流水,type 区分赚取/消耗,description 记清楚是哪笔业务。个人中心的"积分明细"页直接读这张表------这条链路一通,整个"虚拟货币"的设计就立住了。

发布商品时可以勾选"支持积分兑换"并设定兑换所需积分。买家在商品详情页会同时看到两个按钮:立即购买(现金) 和 积分兑换。

答辩场景下这是极好的演示素材:一个账号积分不够,页面会直接告诉他"还差 X 分";换个高积分账号,一路兑到"已完成",双方各 +20,积分明细里两条流水清清楚楚。


六、管理后台:数据看板是答辩的门面

后端写得再好,第一眼看到的是界面。

后台用 Vue3 + Element Plus + ECharts,10 个页面。其中 Dashboard.vue 是重点:顶部四张总览卡片(用户数 / 商品数 / 订单数 / 成交额),下面是三张图------

  • 近 7 天订单趋势(折线)
  • 分类热度分布(饼图)
  • 商品浏览 Top5(横向条形)

管理员的实际操作链路也完整:商品审核 / 驳回 / 违规下架 、用户启用禁用 / 重置密码、分类增删改、订单监管、公告发布、留言与评价管理。

其中有个业务闭环值得注意:商品审核通过时,自动给卖家奖励 10 积分 ,并且这个奖励只在"首次通过"时生效(audit_status 从 0 变成 1 的那一刻)。这防止了卖家反复下架再上架刷积分------一个很小的细节,但体现了你把业务想通了。

java 复制代码
pointsService.changePoints(product.getSellerId(), 10,
    "商品《" + product.getTitle() + "》审核通过奖励");

八、快速开始(真的只要四步)

bash 复制代码
# 1. 数据库
# MySQL 里执行 server/sql/init.sql,自动建库 shiguang + 建表 + 灌种子数据

# 2. 后端
# 改 server/src/main/resources/application.yml 里的数据库账号密码,启动,端口 8080

# 3. 管理后台
cd admin-web && npm install && npm run dev   # 已配好代理到 8080

# 4. 小程序
# 微信开发者工具导入 miniprogram 目录(测试号即可)
# 详情设置里勾选「不校验合法域名」
# 真机预览:把 utils/request.js 里的 BASE_URL 改成电脑局域网 IP

默认账号:

角色 账号 密码
管理员(后台) admin 123456
普通用户(小程序) xiaolin / xiaowang / xiaochen 123456

演示建议开两个账号 :xiaolin(120 积分,5 件在售商品)当卖家,xiaowang(60 积分)当买家。这样一来一回,从发布、审核、下单、支付、自提、评价,全链路都能在一个下午内演示完。


九、适合谁用

这个项目不是给"想要一个能直接上线运营的产品"的人准备的,它偏教学与实训场景。但它能覆盖:

  • 计算机 / 软件工程实训:选题合规、业务完整、三端齐全、有创新点(积分体系 + ISBN 识别)
  • 课程设计 / 大实训:6200 行代码不算夸张,但结构清晰,容易讲明白
  • 面试作品集:三端 + 状态机 + 权限拦截 + 图表看板,比单一 CRUD 项目有说服力
  • 前端转行学全栈项目-- SpringBoot + 小程序全栈的练手项目 :init.sql 一键起库,改个配置就能跑

如果你的选题是"校园二手"方向,这套代码可以直接当骨架,把 isbn 换成你要的业务字段、把积分规则改一改,一天就能改成你自己的题目。


十、写在最后

做这个项目的时候,我一直在想一个问题:为什么校园二手平台这么多,真正在用的却没几个?

后来想明白了------问题不在技术,在"便利性"。任何让学生多点两次屏幕的方案都会失败,因为他们宁可下楼摆摊。

所以这个项目里我刻意砍掉了很多"看起来很厉害"的功能:没做站内 IM(改成商品留言板 + 卖家回复,异步沟通反而更真)、没做物流(校内自提点)、没做复杂搜索(关键词 + 分类 + 三种排序就够)。

砍功能比加功能难,因为砍掉的每一处都在问答时会被追问。但如果能讲清楚"为什么不这么做",这本身就是设计能力的证明。

项目名:拾光流转 ------ 校园二手教材与闲置物品循环交易平台

技术栈:SpringBoot3 + Vue3 + 原生微信小程序

规模:9 表 / 56 接口 / 三端 6200+ 行 / 14 个小程序页面

如果需要一个三端齐全的全栈骨架校园二手 / 跳蚤市场方向的实训项目,这个正合适。

相关推荐
冒险的豆子4 小时前
Proxy & Vue 响应式(合并精简版,适合面试)
前端·javascript·vue.js
Java后端的Ai之路4 小时前
前端技术Vue-18-视图中的渲染
前端·javascript·vue.js
码士集团小青10 小时前
SpringBoot 集成缓存性能之王 Caffeine
spring boot·后端·缓存
凯凯姜13 小时前
MySQL 联合索引设计与索引失效
数据库·mysql
濮水大叔14 小时前
函数式与对象式:前端架构的两种成本曲线
vue.js·react.js·函数式编程
专业程序开发源14 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
莫逸风15 小时前
【毕设源码二期01】校园失物招领系统:从发布线索到核验交接
spring boot·毕业设计·课程设计·react
vx_Biye_Design15 小时前
django房屋租赁推荐系统78455-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·express
林恒smileZAZ16 小时前
浏览器为什么加载不了超大图片
前端·vue.js·html5