资讯动态

基于Spring Boot的B2B商旅小程序:差旅审批到住行订购全解析

发布时间:2026/10/19 6:16:04 来源:尧图企业网站定制
毕设季一到后台私信里问“出差商旅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 拦截器无状态小程序端方便携带前端微信小程序原生原生WXMLJS接口调用简单接口文档Swagger/Knife4j答辩演示时可以直接打开接口页面看效果2.2 小程序端技术栈选择原生还是跨端这个题目下“小程序”大概率默认是微信小程序。前端可以选原生、uni-app、Taro但我的建议是能原生就原生。原因很简单——原生小程序不需要额外编译链微信开发者工具打开就能真机预览代码量对于毕设规模完全够用uni-app虽然能一套代码多端发布但如果你本来就没打算发布到支付宝/抖音小程序它的价值就体现不出来反而会增加vue语法、路由差异等学习成本。原生小程序的核心结构也就四部分app.js处理全局登录状态app.json配置页面路由和tabBarutils/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 预订额度与费用中心的校验逻辑审批通过后员工开始预订酒店或机票这时后端要做“差旅政策校验”核心校验项有三个住宿标准校验根据员工差旅等级查出可预订的最高酒店星级、最高单晚价格上限。例如“一级”可订500元以下酒店“二级”可订800元以下。交通标准校验不同等级对应不同舱位/席别。例如高铁只能订二等座机票只能订经济舱。机票库存表里要设计舱位等级字段预订时直接校验。总额与超标处理同一差旅申请单下已预订金额加上本次预订金额不得超过申请单预估费用的某一比例例如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 RTripApplyVO 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配合微信小程序的登录不能走传统账号密码标准流程是小程序端wx.login()拿到code前端把code发给后端POST /api/auth/login后端拿code调用“微信接口换取 openid”在真实部署时需要 AppSecret毕设阶段一般用测试号或绕过微信登录但流程要写清楚后端查询员工表找到这个 openid 对应的员工记录生成 JWT 返回给前端前端把 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。解决办法有两个在微信开发者工具中勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”然后用局域网IP访问比如http://192.168.31.xx:8080。后端网关层配置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”的自然日天数酒店晚数则在预订接口里单独按“入住日期到离店日期”计算。不要在这个字段上留歧义否则论文里的需求描述会自相矛盾。还有日期传输格式问题。前后端日期建议统一用Stringyyyy-MM-dd传输后端用LocalDate接收并配置Jackson序列化格式避免Date类型带来的时区偏移导致“早一天晚一天”的诡异Bug。5.3 并发下单导致的库存超卖酒店资源表或交通资源表都有“剩余可售数量”这种库存概念。如果多个人同时下单简单的SELECT stock FROM room WHERE room_id ?判断再UPDATE100%会出现超卖。毕设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里解析当前登录员工的IDLong currentEmployeeId JwtUtil.getEmployeeId(request.getHeader(Authorization)); Long companyId employeeService.getById(currentEmployeeId).getCompanyId(); LambdaQueryWrapperBookingOrder 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 测试章节功能测试、并发测试、验收标准系统测试是论文里最“卷”也最好拿分的部分。除了常规的功能测试用例表编号、输入、预期输出、实际输出、结论建议增加两类测试并发测试用JMeter或者Postman的Runner模拟20个用户同时提交酒店订单然后截图断言“库存没有超卖”。这个测试结果放进论文评委印象分会很高。异常流程测试比如审批驳回后重新提交、订单超时释放库存、Token过期访问受保护接口这几类异常场景都必须有一条对应的测试用例和结果。测试用例表格式参考用例编号测试场景操作步骤预期结果实际结果TC-08员工提交超标差旅申请申请费用超过5000元自动进入二级审批提示“需财务总监审批”符合预期TC-13并发抢占同一房型20并发请求同一间房成功下单数量不超过库存总数符合预期有这张表论文的“测试分析”一章基本就稳了也顺便回答了答辩常见的“你怎么验证系统可靠性”这个问题。最后再分享一点关于“调试定制”的体会拿到任何一套代码别急着改功能先看数据库脚本、配置文件、启动类按“建库—导数据—启后端—联调小程序—跑通核心链路”的顺序走一遍。核心链路跑通之后再根据你的论文选题去定制功能比如加一个“差旅超标提醒”、加一个“月度统计报表”这些小改动都是答辩时能拿出来讲亮点的东西。按照这个节奏做一周时间足以把一个平平无奇的模板项目变成论文里能站得住脚的完整系统。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑