☰
基于Spring Boot的B2B商旅小程序:差旅审批到住行订购全解析
2026/10/19 6:15:53 网站建设 项目流程

毕设季一到,后台私信里问“出差商旅B2B商务出行住行订购小程序”怎么做的同学明显多了。这个题目确实很讨巧——业务场景是“企业员工出差,在线定酒店、定机票/高铁票”,技术上又是标准的Spring Boot + 小程序前后端分离,既能秀出后端设计能力,又能展示真实业务流程的理解。我前前后后帮人排查过不少同类型的毕设Demo,今天就把这类项目的完整拆解思路、核心模块设计、后端接口要点、小程序联调方法、文档整理套路一次讲清楚。不管你是打算自己从零写,还是拿到一套代码后要调试定制、写论文答辩,这篇文章都值得花十分钟看完。

1. 先搞清楚这个毕设到底在做什么——B2B商旅小程序的业务本质与需求拆解

1.1 从“出差审批”到“住行订购”:它和C端个人出行App的本质区别

很多第一次接触这个题目的同学,第一反应是“这不就是一个订酒店、订机票的小程序吗,跟携程、美团差不多”。如果真按这个思路去做,恭喜你,从需求分析环节就跑偏了,后面写论文也会被答辩老师追问到哑口无言。

B2B商旅和C端个人出行的核心区别在于:买不买单的人,和使用服务的人不是同一个。在C端场景里,用户自己下单、自己支付、自己享受服务,整个流程是“一个人闭环”;而在B2B差旅场景里,员工出差订票订房,钱是企业出的,谁有资格订、能订什么标准的酒店、能不能超标、超标的部分谁承担,这些问题都不是员工个人能决定的,背后牵着一整套“差旅政策 + 审批流程 + 对公结算”。

所以做这个项目,需求分析的起点不是“怎么搜索酒店”,而是“企业怎么管控员工出差过程中的住行消费”。系统里至少要有四类角色:发起出差申请的普通员工、做审批的管理者、负责对账结算的财务人员、以及管理企业信息和企业差旅策略的系统管理员。

1.2 角色模型与核心用例:员工、审批人、财务、管理员

按照典型的B2B差旅系统设计,项目可以拆成以下几个核心用例组:

  • 员工端用例:提交出差申请单(出差城市、起止日期、预估行程)、查看审批进度、审批通过后预订酒店和交通工具、查看个人差旅订单和历史记录、提交超标说明或自行补差价。
  • 审批端用例:查看待审批列表、同意或驳回申请、对超标准申请进行“特批”或“降级”。
  • 财务端用例:查看企业所有员工的差旅订单、按费用中心/部门汇总消费金额、导出月度对账单、标记发票状态。
  • 管理员端用例:维护企业信息、设置差旅等级标准(比如“部门经理可订四星级及以下酒店、可乘坐高铁一等座”)、管理供应商产品(酒店房型、可售机票舱位等)。

如果你的项目里还做了一个“后台管理端”(一般是Vue或若依框架改造的Web后台),那管理员这部分逻辑就放在Web端;如果图省事,也可以把管理员功能塞进小程序,但界面会很挤,不建议。

1.3 标题里“住行订购”四个字的落地范围

“住行订购”这四个字看着简单,实际功能拆分下来并不少:

  • “住”:酒店搜索、按城市/日期/星级筛选、房型选择、按企业协议价展示价格、提交预订、入住人信息维护。
  • “行”:机票/火车票搜索、班次选择、乘机人/乘车人选择、舱位/座位等级校验。
  • “订购”:不只是“生成一条订单”,而是要把住宿订单和交通订单挂到同一个差旅申请单下,方便财务统一结算。

我见过不少同学做这个题,最后做成了两个毫无关联的模块——“酒店预订”和“机票预订”各写各的,订单表里连差旅单号都没有,这完全没理解B2B商旅的语义。正确的做法是:差旅申请单是主聚合根,住宿订单和交通出行订单都隶属于某一条差旅申请,这样审批、预算、结算才能串起来。

2. 技术选型与项目骨架:Spring Boot + 小程序 + MySQL 的合理组合

2.1 为什么是Spring Boot而不是SSH/SSM

选题是“基于Spring Boot”,这本身就已经避免了老框架的坑。Spring Boot的核心价值是自动配置 + 起步依赖,你只需要引入spring-boot-starter-web、mybatis-plus-boot-starter,再写上对应的配置,项目就能跑起来,不需要像SSM那样写一堆XML配置文件去装配SqlSessionFactory和事务管理器。

对毕设项目而言,Spring Boot还有一个隐性好处:它和微服务概念天然沾边——spring-boot-starter-actuator可以把健康检查、接口信息暴露出来,论文里写一句“系统基于Spring Boot构建,能够快速集成第三方组件,为后续微服务化演进提供基础”,这一个论点就比SSH有说服力得多。

推荐的技术栈组合:

分层推荐选型说明
后端框架Spring Boot 2.7.x稳定,资料多,避免Spring Boot 3搭配JDK17带来的兼容问题
ORMMyBatis Plus代码生成、分页插件好用,适合快速出功能
数据库MySQL 8.x企业场景标准选择
缓存Redis用于登录Token、热点房间库存、验证码等
鉴权JWT + 拦截器无状态,小程序端方便携带
前端微信小程序原生原生WXML+JS,接口调用简单
接口文档Swagger/Knife4j答辩演示时可以直接打开接口页面看效果

2.2 小程序端技术栈选择:原生还是跨端

这个题目下,“小程序”大概率默认是微信小程序。前端可以选原生、uni-app、Taro,但我的建议是:能原生就原生。原因很简单——原生小程序不需要额外编译链,微信开发者工具打开就能真机预览,代码量对于毕设规模完全够用;uni-app虽然能一套代码多端发布,但如果你本来就没打算发布到支付宝/抖音小程序,它的价值就体现不出来,反而会增加vue语法、路由差异等学习成本。

原生小程序的核心结构也就四部分:app.js处理全局登录状态,app.json配置页面路由和tabBar,utils/request.js统一封装后端请求,pages/下面按模块放页面。对于“差旅申请 + 酒店列表 + 订单详情”这种业务,二十来个页面足以覆盖。

2.3 数据库设计的几条主线:员工表、企业表、订单表、结算表

数据库是论文答辩的高频提问区,但你不需要把表设计得特别花哨,核心抓住四条主线:

第一条线:企业组织架构。核心表包括企业表、部门表、员工表。员工表必须冗余字段:员工所属企业ID、部门ID、职级、差旅等级。为什么冗余?因为差旅审批和价格策略都需要立刻判断“这个人能订什么标准的房间和舱位”,如果每次都去关联企业表再查等级配置,SQL会越来越复杂。

第二条线:差旅申请与审批。核心表是差旅申请单表,字段包括:申请单编号、申请人ID、企业ID、出差城市、开始日期、结束日期、预估费用、状态字段(草稿/待审批/已通过/已驳回/已取消)、当前审批节点等。审批记录单独建一张表,记录每个审批人、动作、时间、意见,这对论文的“审批流程设计”章节是很好的支撑材料。

第三条线:住行产品与订单。酒店产品表、机票产品表(或者统称可售资源表),再建订单主表和订单明细表。订单主表除了订单号、类型、金额、状态,还必须有两个关键字段:所属差旅申请单ID、所属企业ID。前面提到过的“聚合”语义就在这里落地。

第四条线:结算与对账。企业月结/挂账模式下,订单支付后不会立即完成资金清算,而是进入“待结算”池,财务确认后生成结算单,结算单再关联一批订单。

3. 后端核心难点拆解:审批流、费用控制、对公结算的状态机设计

3.1 差旅申请单的状态流转与审批链

审批流是这类项目最容易被答辩老师追问的部分。你要明确回答“审批状态在哪些条件下发生迁移”。一个标准的差旅申请单状态机可以这样设计:

  • DRAFT(草稿):员工保存但未提交,可修改、可删除;
  • PENDING_APPROVAL(待审批):员工提交后进入审批队列,不能再编辑;
  • APPROVED(已通过):审批通过后,系统解锁“预订”入口;
  • REJECTED(已驳回):审批被驳回,员工可以修改后重新提交;
  • CANCELED(已取消):审批通过前员工可主动撤回取消;
  • COMPLETED(已完成):订单全部执行完毕且完成结算后,申请单归档。

审批链这里有个设计亮点:多级审批。别把审批人写死成“部门经理”,而是在提交申请时根据申请金额自动找审批链。比如:预估费用小于5000元只需直属领导审批,大于5000元还需要财务总监审批。实现上可以在数据库存一张“审批配置表”,按金额区间配置不同节点数,这样论文的用例图和业务复杂度都会显著提升。

3.2 预订额度与费用中心的校验逻辑

审批通过后,员工开始预订酒店或机票,这时后端要做“差旅政策校验”,核心校验项有三个:

  1. 住宿标准校验:根据员工差旅等级,查出可预订的最高酒店星级、最高单晚价格上限。例如“一级”可订500元以下酒店,“二级”可订800元以下。
  2. 交通标准校验:不同等级对应不同舱位/席别。例如高铁只能订二等座,机票只能订经济舱。机票库存表里要设计舱位等级字段,预订时直接校验。
  3. 总额与超标处理:同一差旅申请单下,已预订金额加上本次预订金额不得超过申请单预估费用的某一比例(例如120%)。如果超标,要么提示员工“超标自付”,要么生成一个“超标申请”进入审批流。

费用中心这块建议在申请单上维护一个costCenterId(成本中心),既方便财务归集成本,也方便论文里写“系统实现了多维度的企业成本管控”,这属于加分项。

3.3 住行订单合并与结算状态机

酒店订单和机票/高铁订单虽然产品类型不同,但在结算层面必须统一。推荐做法是:一个差旅申请单下,可以有多条产品订单(order),每条订单的orderType字段区分HOTEL和TRANSPORT;每个订单有独立的订单状态机:

  • CREATED已创建 →LOCKED已锁定(占用库存)→SETTLED已结算 →COMPLETED已完成;
  • 异常分支:LOCKED状态下超时未确认自动释放库存,变成CANCELED已取消;
  • 退款分支:SETTLED后部分退款,生成退款单。

“已锁定”这个状态很关键。B2B场景下,预订到结算之间往往有时间差,不是即时支付。员工点击“提交订单”时,系统先把房间/座位库存锁住,此时订单是“LOCKED”状态;后端有一个定时任务扫描超过15分钟未进入结算的订单,自动释放库存。这是很经典的“超时释放”设计,答辩时你可以直接结合定时任务说明,可信度很高。

3.4 接口设计示例:差旅下单与审批回调

用代码说话比长篇大论更直观。下面是核心的“创建差旅申请 + 发起预订”接口设计思路:

@PostMapping("/api/trip/apply") public R<TripApplyVO> createApply(@RequestBody TripApplyDTO dto) { // 1. 基础校验:员工是否存在、企业状态是否正常 Employee employee = employeeService.getById(dto.getEmployeeId()); Assert.notNull(employee, "员工不存在"); // 2. 构建申请单主数据 TripApply apply = new TripApply(); apply.setApplyNo("AP" + System.currentTimeMillis()); apply.setEmployeeId(employee.getId()); apply.setCompanyId(employee.getCompanyId()); apply.setStatus(TripStatus.DRAFT); // ... 其他字段赋值,包括费用中心、差旅日期等 // 3. 存储并返回 tripApplyService.save(apply); return R.ok(TripApplyVO.from(apply)); }

预订酒店的接口核心逻辑是“先锁定库存,再生成订单”:

@Transactional(rollbackFor = Exception.class) public BookingOrder lockHotelRoom(LockHotelRoomDTO dto) { // 1. 校验差旅申请单状态 TripApply apply = tripApplyService.getById(dto.getApplyId()); Assert.isTrue(TripStatus.APPROVED.equals(apply.getStatus()), "差旅单未审批通过"); // 2. 校验差旅政策:星级、价格上限 policyChecker.checkHotelPolicy(apply, dto); // 3. 通过Redis分布式锁扣减房间可用数量 boolean locked = redisLock.tryLock("hotel:room:" + dto.getRoomId(), 5, TimeUnit.SECONDS); Assert.isTrue(locked, "系统繁忙,请稍后重试"); // ... 扣减库存,生成订单(LOCKED状态),记录订单日志 }

事务这里有一个容易忽略的坑:扣减Redis库存不能让Redis操作和数据库操作处于同一个本地事务回滚中。建议的做法是:先执行数据库扣减库存(用乐观锁UPDATE room SET stock = stock - 1 WHERE id = ? AND stock > 0),成功后再写订单表;万一写订单失败,再反向补偿库存。虽然多写点代码,但逻辑上更稳妥,也符合分布式事务补偿的思想。

4. 小程序端实现要点:登录、额度展示、行程卡片与支付流程

4.1 小程序登录态如何与后端JWT配合

微信小程序的登录不能走传统账号密码,标准流程是:

  1. 小程序端wx.login()拿到code;
  2. 前端把code发给后端POST /api/auth/login;
  3. 后端拿code调用“微信接口换取 openid”(在真实部署时需要 AppSecret,毕设阶段一般用测试号或绕过微信登录,但流程要写清楚);
  4. 后端查询员工表,找到这个 openid 对应的员工记录,生成 JWT 返回给前端;
  5. 前端把 JWT 存入wx.setStorageSync,之后每个请求在 header 里带Authorization: Bearer <token>。

后端做一个HandlerInterceptor统一处理OPTIONS请求和Token校验,效果最干净。在WebMvcConfigurer里配置拦截器路径:

@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns("/api/**") .excludePathPatterns("/api/auth/login", "/api/auth/code"); }

4.2 首页与行程列表的数据组装

员工进入小程序,首页一般长这样:顶部是“出差申请”按钮,中间是“进行中的差旅”卡片,下面是历史行程列表。这里的核心是后端聚合接口GET /api/trip/myTrips,返回结构可以设计为:

{ "ingList": [ { "applyNo": "AP...", "city": "上海", "startDate": "2025-06-01", "endDate": "2025-06-03", "status": "APPROVED", "hotelOrder": { "hotelName": "...", "roomType": "..." }, "transportOrder": { "trainNo": "G1234", "seatClass": "二等座" } } ], "historyList": [] }

这样做的好处是首页一次请求就能把“待审批、已通过、进行中”聚合展示,不用前端多次拉接口再拼装。小程序端的onLoad里request.get('/api/trip/myTrips')渲染列表即可。

4.3 支付/挂账场景:B2B不需要真实线上支付的取舍

没有做过企业项目的同学很容易在“支付”这个问题上卡住。我要强调一遍:B2B商旅几乎不做真实线上支付,而是“企业挂账月结”。所以在你的项目里,不需要接入微信支付API,这一点反而能在论文中作为业务特色表达。

具体实现上,订单创建后直接进入“待结算”池,财务后台点击“确认结算”后,订单状态变为SETTLED,同时生成一条结算记录(结算单号、企业ID、订单ID、金额、结算时间、操作人)。如果非要模拟“账户余额支付”,可以在员工表或企业表加一个“差旅预算余额”,下单时扣余额,结算时按总额回写。这已经是进阶功能了,毕设规模可做可不做,但做了绝对能加分。

5. 调试与定制阶段的高频问题:我排查过的那些坑

5.1 小程序真机预览连不上本地Spring Boot服务

这可能是所有Spring Boot + 小程序项目里出现率最高的问题。在开发者工具里用http://localhost:8080能请求通,一上真机就全部失败。原因很简单:手机上的小程序不能访问你电脑的localhost。

解决办法有两个:

  1. 在微信开发者工具中勾选“不校验合法域名、web-view(业务域名)、TLS版本以及HTTPS证书”,然后用局域网IP访问,比如http://192.168.31.xx:8080。
  2. 后端网关层配置cors和server.address,确保启动时监听0.0.0.0,而不是默认的127.0.0.1。

另外,小程序原生request的url不能带空格和中文参数,所有参数要么拼在路径里,要么用data对象传,这个在调试地址拼接时很容易踩中。

5.2 日期跨天与差旅天数的边界问题

差旅申请里,startDate和endDate看起来简单,算天数却有坑:6月1日到6月3日,有些人算2天(6月1日晚到6月3日早),有些人算3天(三个自然日)。这个语义不统一,后面“住宿晚数”和“预估费用”都会错。

我的建议是:在实体层统一一个工具方法calcTripDays(startDate, endDate),明确规则为“结束日期减开始日期 + 1”的自然日天数,酒店晚数则在预订接口里单独按“入住日期到离店日期”计算。不要在这个字段上留歧义,否则论文里的需求描述会自相矛盾。

还有日期传输格式问题。前后端日期建议统一用String(yyyy-MM-dd)传输,后端用LocalDate接收并配置Jackson序列化格式,避免Date类型带来的时区偏移导致“早一天晚一天”的诡异Bug。

5.3 并发下单导致的库存超卖

酒店资源表或交通资源表都有“剩余可售数量”这种库存概念。如果多个人同时下单,简单的SELECT stock FROM room WHERE room_id = ?判断再UPDATE,100%会出现超卖。毕设Debug阶段很可能遇到。

修复方案是改用乐观锁更新:

UPDATE hotel_room SET stock = stock - 1, version = version + 1 WHERE id = #{roomId} AND stock > 0 AND version = #{version}

如果影响行数为0,说明库存已被抢完或版本号冲突,需要重新查询再决定是否提示“已售罄”。这个点答辩时非常容易被问到,务必写在论文的“系统性能与并发”小节里。

5.4 权限控制中的越权问题

很多同学在写订单查询接口时,只写SELECT * FROM booking_order WHERE employee_id = ?,参数是前端传的用户ID。这就是严重的越权漏洞——A员工改一下请求参数,就能看到B员工甚至其他企业的订单。

正确做法是:后端不要信任前端传的ID,统一从JWT里解析当前登录员工的ID:

Long currentEmployeeId = JwtUtil.getEmployeeId(request.getHeader("Authorization")); Long companyId = employeeService.getById(currentEmployeeId).getCompanyId(); LambdaQueryWrapper<BookingOrder> wrapper = Wrappers.lambdaQuery(); wrapper.eq(BookingOrder::getEmployeeId, currentEmployeeId) .eq(BookingOrder::getCompanyId, companyId);

同时,管理员和财务角色的接口要加@RequiresPermissions或自定义权限校验注解,至少要对接口做方法级权限控制。别觉得这是多余设计,这是B2B系统的基本安全底线,写论文、答辩、实际演示都会被问。

6. 毕设文档(LW)怎么写才能撑起答辩:从需求分析到系统测试

6.1 需求分析部分怎么从业务流程提炼

论文里最忌“这个系统是为了提高效率所以很有必要”。正确写法是:先画一张企业差旅业务现状图,指出“审批线下进行、预订渠道分散、结算靠人工对账、超标无法控制”这些痛点,然后逐条对应到系统功能需求表。

功能需求表可以用“编号-功能模块-功能描述-优先级”四列表格,比如:

编号功能模块功能描述优先级
FR-01差旅申请员工填写出差城市、起止日期、预估费用、成本中心高
FR-02审批管理按金额区间自动匹配审批链,支持同意/驳回/特批高
FR-03酒店预订按差旅等级筛选可订房型,锁定库存生成订单高
FR-04交通预订支持机票/高铁舱位等级校验高
FR-05对公结算财务按企业维度汇总订单生成结算单中

论文里放这种表,答辩老师一眼就能看出你确实理清了业务需求,比大段大段写“系统功能有权限管理、用户管理、订单管理”要高出好几个段位。

6.2 系统设计部分:ER图、用例图、时序图的组织

这一章如果不是画图,就不要只贴代码。标准素材是三张图:

  • 用例图:四个角色各有哪些用例,UML用例图能把“员工-申请-审批”的边界表达得很清楚;
  • ER图:至少把企业、员工、差旅申请单、订单、审批记录、结算单这六张表的关系画出来,表明一对多关系;
  • 时序图:重点画“创建差旅申请→审批→预订酒店→锁定库存→生成订单→财务结算”这条主链路。

作图工具随便选,draw.io或ProcessOn都可以。注意ER图不要画超过12张表,毕设规模画太复杂反而容易被问倒。我在给同学做辅导时常说:图里的每一条线、每一个外键,你都要准备好一分钟讲清楚“为什么要这样关联”,讲不清的干脆不要画。

6.3 测试章节:功能测试、并发测试、验收标准

系统测试是论文里最“卷”也最好拿分的部分。除了常规的功能测试用例表(编号、输入、预期输出、实际输出、结论),建议增加两类测试:

  1. 并发测试:用JMeter或者Postman的Runner,模拟20个用户同时提交酒店订单,然后截图断言“库存没有超卖”。这个测试结果放进论文,评委印象分会很高。
  2. 异常流程测试:比如审批驳回后重新提交、订单超时释放库存、Token过期访问受保护接口这几类异常场景,都必须有一条对应的测试用例和结果。

测试用例表格式参考:

用例编号测试场景操作步骤预期结果实际结果
TC-08员工提交超标差旅申请申请费用超过5000元自动进入二级审批,提示“需财务总监审批”符合预期
TC-13并发抢占同一房型20并发请求同一间房成功下单数量不超过库存总数符合预期

有这张表,论文的“测试分析”一章基本就稳了,也顺便回答了答辩常见的“你怎么验证系统可靠性”这个问题。

最后再分享一点关于“调试定制”的体会:拿到任何一套代码,别急着改功能,先看数据库脚本、配置文件、启动类,按“建库—导数据—启后端—联调小程序—跑通核心链路”的顺序走一遍。核心链路跑通之后,再根据你的论文选题去定制功能,比如加一个“差旅超标提醒”、加一个“月度统计报表”,这些小改动都是答辩时能拿出来讲亮点的东西。按照这个节奏做,一周时间足以把一个平平无奇的模板项目变成论文里能站得住脚的完整系统。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询