
如果你正在为毕业设计选题发愁又想把Java后端和微信小程序前端完整地串起来练一遍我强烈建议你看看共享茶室预约系统这个方向。它表面上只是一个“订房间”的小程序但做进去以后你会发现它同时牵扯到了微信登录、分布式锁、订单状态机、定时任务、小程序端交互甚至支付流程——无论从毕设的工作量、技术深度还是答辩可讲的故事性来说都是一个性价比极高的题目。这篇文章我就以SpringBoot 微信小程序这套技术栈为例把整个项目从需求拆解、技术选型、数据库设计到后端核心逻辑、小程序端开发、部署答辩的完整链路都过一遍并把我在实际开发中踩过的坑一并写出来给你当参考。1. 共享茶室的需求并不简单从线下场景到线上系统的边界划分1.1 无人茶室和传统酒店民宿预订有什么不同很多同学拿到这个题目之后第一反应是“这不就是酒店预订系统换个皮吗”于是照着民宿系统的思路去建表房间、订单、用户然后提交就完事了。这个思路不能说错但没有抓住无人茶室的核心差异。酒店预订通常按“晚”计费前台有人办理入住房间是固定的。共享茶室不一样它是按“小时/时段”计费的而且大概率是无人值守。用户在小程序上完成选择茶室、选择时间段、支付之后真正到了线下是需要自己扫码进门、自己使用茶具茶叶到时间后关门走人。这意味着什么意味着订单支付成功绝对不是服务的终点而是线下履约的起点。系统里必须有一套完整的“履约状态”来跟踪每个订单用户到了没有使用时间到了没有房间有没有被释放超时未支付该怎么办这些都不是传统酒店系统需要花太多精力去考虑的事情。所以做这个项目之前先把“无人化”三个字刻在脑子里后面的数据库设计和逻辑才不会跑偏。1.2 系统涉及的三类角色与核心流程我分析下来这个项目至少需要三类角色用户搜索和浏览茶室查看某一日期某个房间的空闲时段选择时段后下单支付到店后凭订单生成的开门码开门使用期间可以续时使用完毕后订单自动完成。经营者/管理员维护茶室基本信息维护房间、时段价格查看订单流水处理退款统计每天的营收和出租率。系统后台任务自动关闭超时未支付订单到开始时间自动把订单置为“使用中”到结束时间自动释放房间并把订单置为“已完成”。这三类角色对应的核心业务流程是一个闭环用户注册登录 → 浏览选房 → 锁定时段 → 支付 → 生成开门凭证 → 到店履约 → 订单完成 → 数据沉淀到管理员后台。毕设答辩的时候能把这个闭环讲清楚比堆砌一堆CRUD功能管用得多。1.3 功能边界哪些模块别在毕设里硬做我觉得这个题目最大的诱惑在于“无人茶室”听起来很酷很容易让人想着去接真实硬件智能门锁、环境传感器、语音播报甚至自动泡茶机。我劝你冷静一点。毕设的时间有限核心是把这个业务系统做完整而不是把硬件全部打通。硬件接入可以作为扩展点写进论文的展望里真机实现反而不是必需品。比如门锁这块你可以做一个“开门码”的模拟用户订单支付成功并到达开始时间后订单详情页显示一个短码页面提示“前台无人值守请凭开门码进入对应房间”。演示的时候管理员在系统后台输入这个短码确认后订单状态变为“使用中”。这样既不买硬件又完整地展示了无人茶室的开锁履约闭环。把这个思路讲给评委听他们反而会觉得你有工程意识知道用最小成本验证核心逻辑。2. 技术选型复盘为什么是SpringBoot 微信小程序 MySQL Redis2.1 SpringBoot为何是这类毕设的稳妥选择后端框架我选了SpringBoot原因很实在配置少、内嵌Tomcat、一键打包成JAR对毕设这种需要快速出成果的场景太友好了。你不需要像传统SSH项目那样写一堆XML配置一个SpringBootApplication就能跑起来。而且SpringBoot的资料多到爆炸任何报错基本都能搜到解决方案这对做毕设的学生来说是巨大的隐形助力。版本选择上我建议SpringBoot 2.7.x配JDK 1.8或11不要上来就追新用SpringBoot 3。倒不是SpringBoot 3不好而是很多第三方库比如MyBatis-Plus、一些生成验证码的组件在SpringBoot 3下的兼容方式和之前不一样容易让人卡在环境问题上。毕设求稳技术版本不要当小白鼠。ORM方面直接上MyBatis-Plus。它不用写繁琐的XML映射LambdaQueryWrapper写条件查询非常顺手分页插件也集成好了。更关键的是它默认用雪花算法生成主键省掉了我手动处理主键生成的麻烦。如果你想偷个懒还可以用它的代码生成器连实体类、Mapper、Service都一次性生成出来省下的时间用来打磨核心逻辑。2.2 小程序端原生开发还是uni-app小程序端我当时纠结过一段时间是用原生微信小程序还是用uni-app。最后选了原生。理由很简单页面就首页茶室列表、茶室房间列表、预约下单、订单列表、个人中心这几个用原生写完全够。原生的调试工具、真机预览、开发者文档都是微信官方维护的遇到问题能少踩很多坑。而且如果你以后想转uni-app原生小程序的核心概念比如setData、wx.request、生命周期函数也是相通的转换成本不高。如果你有跨端需求比如以后还想发支付宝小程序那可以选uni-app。但纯为了毕设我建议别在这上面纠结原生省心。2.3 Redis在预约系统里的三种典型用法这个项目里的Redis不是摆设是真真实实能解决三大问题第一存放登录态和权限标记。虽然我用JWT做无状态认证但有时候需要支持服务端强制下线比如用户在小程序端退出登录。我用Redis存了一份token - userId的映射校验请求时先查Redis能查到才放行。这样用户退出登录后我直接删掉Redis里的键原有的JWT就立刻失效了。第二实现锁座。同一间茶室在某个日期某个时段同时只能被一个人预约。这个问题靠数据库唯一索引可以做兜底但更好的做法是在下单前先用SETNX命令加一把Redis分布式锁防止并发请求同时查到“有空”然后一起下单。第三生成全局有序的订单号。订单号我采用“前缀 日期 Redis自增序列”的方式比如TEA202501181200001。这里用的就是Redis的INCR命令非常方便。这里有个热搜词提到的坑RedisTemplate调用increment()时如果你直接把返回值解析成Integer或者往一个原本是字符串类型的key上执行自增操作很容易报“ERR increment or decrement would not be an integer or out of range”。正确做法是返回值用Long接收并且保证这个key的初始值就是数字类型不要先存了字符串再去自增。这种错在本地自测很容易踩提前给你打个预防针。2.4 环境配置和版本雷区环境配置环节看着简单其实有一堆细节。JDK装好后一定要手动配好JAVA_HOME和PATH不然IDE能识别但命令行打包会报“java不是内部或外部命令”。Maven的话务必换国内镜像不换镜像的话首次下载SpringBoot依赖能等得你怀疑人生。还有一个小细节Maven编译级别要和JDK版本匹配别让IDE的Project SDK是17Maven的java.version还写着1.8那样会编译报错。SpringBoot和MyBatis-Plus的版本匹配也要留意。如果你的SpringBoot用的是3.x一定要引入mybatis-plus-spring-boot3-starter而不是旧的mybatis-plus-boot-starter。很多同学项目启动报ClassNotFoundException找半天最后发现是版本不匹配。3. 数据库设计与接口定义房态、时段、订单这三张表才是核心3.1 核心表结构设计数据库设计我建议从“一间茶室怎么被预订”这个视角去反推。一共需要这么几张核心表tea_house茶室表存储茶室名称、地址、联系电话、营业开始和结束时间、状态营业/停业。tea_room房间表存储房间所属茶室ID、房间编号、可容纳人数、每时段价格、房间图片、环境描述。room_slot时段库存表存储某天某个时段某个房间的可预订状态。字段至少包括房间ID、日期、开始时间、结束时间、状态可预订/已锁定/已使用。这张表是预约功能的核心。orders订单表订单号、用户ID、房间ID、日期、开始时间、结束时间、金额、订单状态、开门码、微信支付交易号、创建时间、支付时间。user用户表微信openid、昵称、头像、手机号可选、注册时间。room_slot表和orders表要分开。房间和时间段是“资源”订单是“交易”。资源可以被查询、被锁定、被释放订单则记录一次完整交易的生命周期。这样设计的好处是查询某个时段是否空闲时直接查room_slot表不需要去订单表里做复杂的条件判断性能更好。表结构可以贴一段SQL示例CREATE TABLE room_slot ( id bigint NOT NULL AUTO_INCREMENT, room_id bigint NOT NULL COMMENT 房间ID, slot_date date NOT NULL COMMENT 日期, start_time time NOT NULL COMMENT 开始时间, end_time time NOT NULL COMMENT 结束时间, status tinyint NOT NULL DEFAULT 0 COMMENT 0可预订 1已锁定 2已使用, version int NOT NULL DEFAULT 0 COMMENT 乐观锁版本号, PRIMARY KEY (id), UNIQUE KEY uk_room_date_time (room_id, slot_date, start_time) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT房间时段库存表;3.2 防止同一时段被重复预约防并发重复预约我做了两层保障。第一层是业务前置拦截。下单时我说过会先加Redis分布式锁锁的key就是room_slot表的主键或唯一业务键。拿到锁之后再查一次数据库里的状态确认仍然是“可预订”才继续往下走。这样做的好处是绝大多数并发请求在锁这一层就被拦截了数据库压力很小。第二层是数据库的唯一索引兜底。即使Redis锁失效或者你的代码里忘记加锁唯一索引也能保证同一房间、同一天、同一开始时间只能有一条记录被成功插入或更新。当并发插入时只有一个请求能成功其他的会抛出DuplicateKeyException捕获到这个异常后给用户返回“该时段已被预约”即可。这里再提一个细节如果你用了MyBatis-Plus的save方法插入订单它默认不会告诉你唯一索引冲突只会抛DuplicateKeyException。所以你必须在Service层捕捉这个异常转成业务异常返回给前端否则小程序端看到的是一段难看的500错误JSON。3.3 接口列表与统一返回体设计后端接口按照资源维度可以划分成下面这些足够覆盖小程序端和后台管理端的主要功能模块接口说明用户POST /api/user/login微信登录code换openid返回JWT茶室GET /api/tea-house/list茶室列表支持分页房间GET /api/tea-room/list?houseId某个茶室下的所有房间时段GET /api/slot/available?roomIddate查询某房间某天的可预订时段订单POST /api/order/create创建订单锁定时段订单POST /api/order/mockPay模拟支付用于未开通微信支付时订单POST /api/order/wxPay真实微信支付下单预留订单POST /api/order/pay/notify微信支付回调预留订单POST /api/order/cancel取消订单释放时段订单GET /api/order/my查询我的订单列表订单GET /api/order/detail?id查询订单详情包含开门码所有接口统一返回一个Result对象结构是{ code, message, data }。分页数据放在data里里面包含list、total、pageNum、pageSize。这样小程序端和处理异常的逻辑都能统一不用为每个接口定制返回格式。4. 后端核心逻辑实现微信登录、预约锁座、支付回调与超时释放4.1 微信登录的code2session与JWT签发小程序的登录流程是标准的三步小程序端通过wx.login()拿到一个临时code。小程序把code通过wx.request发送到后端。后端拿到code后调用微信的code2Session接口换取openid和session_key。这里有个特别重要的安全原则小程序的AppSecret绝对不能放在前端代码里否则别人反编译小程序包就能拿到你的密钥后果很严重。前端只负责传code换openid的工作必须放在后端。拿到openid之后我去user表里查一下用户是否存在不存在就自动注册存在就直接登录。登录成功后用openid和用户ID生成一个JWT返回给小程序端。小程序端后续请求只需要在HTTP头里带Authorization: Bearer token后端通过拦截器统一解析。JWT的生成我用了jjwt库代码大致是这样String token Jwts.builder() .setSubject(userId.toString()) .claim(openid, openid) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() 7 * 24 * 60 * 60 * 1000L)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact();要注意JWT里面不要放敏感信息它只是防篡改不是加密。真要防某些极端场景可以配合Redis做二次校验前面已经说过不再重复。4.2 预约下单的核心代码先查库存、再锁座、最后生成订单预约下单是后端最核心的接口我把它的完整逻辑拆成下面几步校验用户是否登录。校验房间ID、日期、开始时间、结束时间是否合法。拼Redis锁的key比如lock:slot:{roomId}:{date}:{startTime}用setIfAbsent加锁设置5分钟过期。加锁成功后查询room_slot确认状态为“可预订”。创建订单状态为“待支付”生成订单号和开门码。更新room_slot状态为“已锁定”。返回订单号给前端引导支付。代码简化后大致长这样Transactional public OrderDTO createOrder(CreateOrderRequest request) { // 校验用户、房间、时段省略 String slotDate request.getSlotDate().toString(); String startTime request.getStartTime().toString(); String lockKey lock:slot: request.getRoomId() : slotDate : startTime; Boolean locked redisTemplate.opsForValue() .setIfAbsent(lockKey, 1, Duration.ofMinutes(5)); if (!Boolean.TRUE.equals(locked)) { throw new BizException(该时段刚刚被预约了请更换时段); } try { RoomSlot slot roomSlotMapper.selectOne(new LambdaQueryWrapperRoomSlot() .eq(RoomSlot::getRoomId, request.getRoomId()) .eq(RoomSlot::getSlotDate, request.getSlotDate()) .eq(RoomSlot::getStartTime, request.getStartTime()) .eq(RoomSlot::getStatus, SlotStatus.AVAILABLE)); if (slot null) { throw new BizException(该时段暂不可预约); } // 创建订单 Order order new Order(); order.setOrderNo(generateOrderNo()); order.setUserId(currentUserId); order.setRoomId(request.getRoomId()); order.setSlotDate(request.getSlotDate()); order.setStartTime(request.getStartTime()); order.setEndTime(request.getEndTime()); order.setAmount(calcAmount(request)); order.setStatus(OrderStatus.WAIT_PAY); order.setOpenCode(generateOpenCode()); orderMapper.insert(order); // 锁定时段 slot.setStatus(SlotStatus.LOCKED); roomSlotMapper.updateById(slot); return OrderDTO.fromEntity(order); } finally { // 注意这里不能立刻删锁订单创建成功后由定时任务或支付回调处理锁释放 // 真正需要释放的是“订单取消或支付成功后把剩余可售库存是否释放”的业务逻辑 } }这段代码里有几个细节值得展开说setIfAbsent加锁时一定要设置过期时间。如果忘了设置过期时间服务宕机后锁永远不释放那个时段就永远订不出去了。创建订单和锁定时段是在同一个事务里的。这样即使第二步失败了第一步锁的库存也不会留下脏数据。但Redis锁本身不是数据库事务的一部分最后释放锁的时机要结合业务状态机来处理不能简单地在finally里把锁删掉。generateOrderNo()用Redis自增序列能保证同一天内订单号是有序的而且一眼就能看出订单是哪天创建的。这个细节在答辩时可以提体现你对业务标识设计有思考。4.3 支付模块的务实做法未开通微信支付时先接Mock支付很多毕业设计卡在支付这一步个人主体小程序不能开通微信支付或者申请不下来导致“小程序微信支付v3对接”成了空中楼阁。我的建议是毕设阶段不要跟真实的微信支付死磕先做一个Mock支付接口把流程走通。Mock支付的逻辑非常简单用户点击“支付”按钮前端调用POST /api/order/mockPay传入订单号。后端直接把订单状态从“待支付”改成“已支付”同时生成开门码实时响应给前端。真实支付和Mock支付的唯一区别在于真实支付需要在用户点击支付后后端调用微信下单API拿到prepay_id等信息前端再调wx.requestPayment拉起收银台用户支付完微信会回调一个异步通知后端验签后更新订单状态。如果你后续想接真实支付流程大概是这样的后端调用微信支付V3的/v3/pay/transactions/jsapi接口入参包含openid、订单号、金额等。微信返回prepay_id后端按照官方规则生成paySign签名。前端使用wx.requestPayment拉起支付。支付完成后微信服务器会向你配置的notify_url发送回调通知携带支付结果。后端接收回调先用WechatPay-Signature验签再解密报文然后更新订单状态。对接真实微信支付比较繁琐特别是V3的证书和验签逻辑不花个一两天很难完全跑通。毕设时间宝贵的同学先把Mock支付流做了然后把这个流程写进文档或者答辩PPT至少表明你知道真实支付应该怎么做是因为资质限制才用了模拟方案而不是不懂。4.4 订单状态机与超时释放订单状态我用一个枚举统一管理从创建到结束一共这么几个状态WAIT_PAY待支付用户下单成功但未支付。如果15分钟内没支付系统自动取消并释放时段。WAIT_USE已支付/待使用支付成功还没到预定开始时间。这个阶段用户可以申请取消取消后退款Mock支付下就直接退款。IN_USE使用中到达开始时间后状态自动变为使用中用户可以看到开门码。FINISHED已完成到达结束时间系统自动完成订单并释放房间。CANCELLED已取消用户主动取消或系统超时取消。REFUNDING退款中预留这个状态方便以后接真实退款流程。状态流转怎么驱动我用的Spring自带的Scheduled定时任务每30秒扫描一次订单表。扫描规则很简单找到所有status WAIT_PAY且create_time超过当前时间15分钟的订单把状态改成CANCELLED并将对应的room_slot状态恢复为“可预订”。找到所有status WAIT_USE且start_time 当前时间的订单把状态改成IN_USE。找到所有status IN_USE且end_time 当前时间的订单把状态改成FINISHED并将对应的room_slot状态恢复为“可预订”。这里要注意如果同一时间并发修改大量订单定时任务里要控制好一次性扫描的范围不要全表一次更新可以分页扫描。另外单机定时任务在毕设环境里够用但你可以在论文里提一句“生产环境建议用XXL-Job或RocketMQ延迟消息来保证分布式和精确性”这样显得你考虑过更复杂的方案。5. 小程序端开发实战预约页面、状态轮询、以及我踩过的API坑5.1 页面结构从首页列表到填单页小程序端我规划了四个主要页面首页茶室列表展示茶室名称、地址、距离省了定位用固定排序、营业时间点击进入房间列表。房间列表与选时页页面顶部是房间图片和环境介绍中间是日期选择器下面是当天各个时段的列表。每个时段用卡片展示开始-结束时间、价格、是否可预订。可预订的绿色已约满的灰色禁用。订单确认页展示选中的茶室、房间、日期、时段、金额底部固定一个“去支付”按钮。我的订单列表按状态Tab切换全部/待支付/待使用/使用中/已完成/已取消。首页的茶室列表不用做太复杂一个wx.request拉取后端接口再用wx:for渲染卡片即可。需要注意图片资源的域名必须加到小程序的downloadFile合法域名里不然图片加载不出来。这个问题很隐蔽很多同学本地开发看着挺好真机预览就全是裂图原因就是域名配置。5.2 登录态管理Token过期与静默登录小程序端的登录态管理我封装了一个request方法和一个ensureLogin方法。ensureLogin的逻辑是进入小程序时先检查本地缓存wx.getStorageSync(token)是否存在。如果存在直接用如果不存在或者后端返回code: 401先调wx.login拿到code再调后端/api/user/login换token最后存到本地。这里有一个特别多初学者会犯的错每次启动小程序都调一次wx.login然后重新拿token。wx.login生成的code是五分钟有效且只能用一次频繁调用既浪费资源又可能在并发请求时搞出“code already used”的报错。正确方式是只在本地没有有效token时才去登录。所有请求统一走封装好的request方法大致结构如下function request(url, method, data) { return new Promise((resolve, reject) { const token wx.getStorageSync(token) wx.request({ url: baseUrl url, method: method, data: data, header: { Content-Type: application/json, Authorization: token ? Bearer token : }, success: (res) { if (res.data.code 200) { resolve(res.data.data) } else if (res.data.code 401) { ensureLogin().then(() { // 重新请求当前接口 }) } else { wx.showToast({ title: res.data.message, icon: none }) reject(res.data) } }, fail: (err) reject(err) }) }) }5.3 常见微信API坑小程序端看起来代码不多但微信生态的坑是真的不少我整理几个我自己踩过的swiper里嵌套video全屏错位如果房间详情页有用swiper轮播展示环境视频真机上点击全屏很容易错位。我的解决方案是放弃在轮播图里放video改成用图片加一个“播放”蒙层点击后跳转到独立视频页播放。这个坑在很多技术社区都能看到提前避掉能省很多时间。手机软键盘遮挡输入框页面里有搜索框或备注框时安卓手机弹起软键盘经常把输入框挡住。解决方案是在input标签上设置cursor-spacing20或者使用adjust-position属性让页面自动上推。setData别传大数据如果一次加载几十条茶室列表直接把整个数组setData到页面上在低端安卓机上会明显卡顿。我的做法是分页加载每次setData只追加20条同时加一个“加载中”提示。时间段选择不要用input正确做法是用picker组件的modemultiSelector用两级联动分别选择日期和开始时间。手动输入时间会带来无穷无尽的格式校验问题纯属给自己找麻烦。这些坑在开发文档里未必会明确写有些是社区经验有些是实测踩出来的。我写在这里希望你做的时候不用再重新踩一遍。6. 部署上线、压测与毕设答辩一些你可能会忽略的细节6.1 打包部署JAR包、Nginx与HTTPS小程序正式环境要求后台接口域名必须为HTTPS而且需要在小程序公众平台里配置合法域名。所以部署这一步不能省。SpringBoot项目打包很简单在项目根目录执行mvn clean package -DskipTests然后会生成一个target/*.jar文件把它上传到云服务器用nohup java -jar xxx.jar 就能跑起来。为了方便管理我建议先装一个Supervisor或systemd服务让进程崩溃后自动重启。这个细节如果写到部署文档里会显得你很专业。因为小程序要求HTTPS云服务器上要有SSL证书Nginx监听443端口把请求反向代理到本地的Java服务端口。Nginx配置核心就这一段server { listen 443 ssl; server_name yourdomain.com; ssl_certificate cert.pem; ssl_certificate_key cert.key; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }如果在本地调试用不到真实HTTPS但你可以在微信开发者工具里勾选“不校验合法域名”这样本地HTTP接口也能正常访问。不过这只限开发环境一上真机预览就必须用合法域名。6.2 并发测试用Jmeter把并发场景跑一遍我建议你写一个简单的Jmeter测试计划重点压/api/order/create这个接口。我当时的做法是模拟200个并发用户同时提交同一个房间、同一天、同一个时段的预约请求。不加Redis锁的时候最终数据库里会插进去好几条相同房间相同时间段的订单而加了锁之后只会有一个请求成功其余的都返回“该时段已被预约”。这个前后对比截图放进毕业论文的“系统测试”章节里非常有说服力。这不仅是“我测过功能”还是“我针对业务难点设计了解决方案并用数据验证了有效性”。另外再测一下超时未支付自动取消的定时任务。你可以手动把一条订单的create_time改成15分钟前然后等定时任务跑完看看订单状态是否变成“已取消”同时对应的room_slot是否恢复成“可预订”。这个测试点虽然没有并发测试那么华丽但能证明你状态机设计是完整的答辩时也可以顺便提一句。6.3 答辩时怎么讲从业务痛点讲到技术方案再讲到扩展第一次答辩的同学很容易犯一个毛病上来就开始讲“我用了SpringBoot建了哪些表写了哪些接口”评委听十分钟就腻了。我更推荐你按照“业务痛点 → 技术选型 → 方案落地 → 测试验证 → 还能扩展”这条线来讲。先讲清楚共享茶室为什么会存在城市里很多茶楼包间闲置率高经营者需要一套系统实现在线预订和无人化运营用户需要线上看时段、预约、支付、到店即用。这个痛点讲两分钟评委就知道你的项目是有场景的不是凭空造的。再讲你如何从痛点推导出功能清单功能清单如何决定你的表结构。比如因为要按时间段预订所以有room_slot表因为要考虑无人履约所以有订单状态机因为要防止并发超卖所以用Redis锁加数据库唯一索引。技术方案不是堆砌的而是跟着业务问题一个一个长出来的这才是答辩中最大的加分项。最后不要忘了画一条扩展线接入真实门锁后订单完成后可以通过MQTT把开门指令下发到设备端接入运营大屏后可以统计不同时段的出租率反向指导茶室定价如果退款流程复杂还可以引入Flowable工作流引擎做审批。这些扩展点不一定要做但你说出来之后评委知道你对这个领域有全局视野。6.4 我做完之后的几点体会这个项目做完我最直观的感受是别急着写代码先把业务闭环画明白。很多同学一上来就建表、写接口到后面发现订单状态缺了一个“使用中”或者没考虑超时未支付释放库存又回头改表结构改来改去把自己绕晕。如果你也准备做共享茶室预约小程序我建议你先在纸上把用户从打开小程序到用完离店的完整流程画一遍把每个环节涉及的数据和状态标注出来再动手编码。流程图画明白之后数据库设计、接口设计、页面设计其实都是水到渠成的事。另外一个很现实的经验要把能演示的东西做得越直观越好。评委不会去看你源码写得多优雅他们最在意的是你能不能现场把一个完整场景跑通。所以哪怕是Mock支付、Mock开门码只要流程能走通就能证明你的系统支撑了完整的业务链路。比你在PPT里贴十页代码有用得多。希望这篇复盘能帮你少走点弯路祝你的毕设一次通过。