在本地生活、家政服务、美容养护、维修服务等线下场景中,到店预约与上门服务是主流的用户消费模式。很多新手开发者在开发这类项目时,容易出现前端预约提交逻辑混乱、后端派单指派冲突、订单状态错乱、结算数据对不上等问题。
整套项目采用目前主流的前后端分离开发模式,移动端使用 UniApp 开发,一套代码可同时适配微信小程序、APP、H5多端展示,兼容性强、开发效率高。后端基于 Java SpringBoot 搭建核心服务,通过 MyBatis 完成数据持久化,Redis 辅助实现预约时段缓存、订单防重、热门服务数据提速加载。前后端通过 JSON 格式接口交互,各司其职,前端专注页面交互、表单校验、状态展示,后端专注业务逻辑、数据校验、派单规则、状态流转与资金结算,架构清晰、分工明确。
本次开发实现的核心业务包含四大模块,覆盖线下服务平台刚需功能。一是双模式预约提交,支持用户自主选择到店消费或上门服务,可自定义预约日期、时段、服务项目、备注信息;二是后台智能指派功能,管理员可手动指派技师,也可开启系统自动指派,优先匹配空闲、在岗技师;三是完整订单状态流转,适配预约待确认、待服务、服务中、已完成、已取消、已退款等全场景状态;四是订单结算功能,支持服务完成后自动核算金额、展示费用明细、生成结算账单,适配线下服务标准化对账需求。
UniApp 前端主要承担用户交互与数据展示工作,针对预约场景做了针对性优化。前端封装统一的预约提交组件,区分到店、上门两种场景表单展示逻辑,上门服务自动展示地址选择、上门距离信息,到店服务默认展示门店选择与到店时段选择。同时前端完成基础表单校验,避免空参数、非法时段等无效请求提交,减轻后端接口压力。订单页面统一适配不同状态的UI展示,根据后端返回的状态码动态切换按钮文案和操作权限,避免用户误操作。
Java 后端是整套业务的核心枢纽,负责处理所有核心规则与数据逻辑。相较于前端静态展示,后端需要精准把控预约时段合法性、技师在岗状态、派单唯一性、订单状态变更链路、结算金额计算规则。为避免业务耦合,后端将预约提交、技师指派、状态流转、订单结算拆分为独立业务方法,保证代码可读性与可维护性,方便后期迭代拓展优惠券抵扣、会员折扣、评价返现等功能。
数据库表结构围绕预约与订单核心业务设计,简洁且贴合实战需求。服务项目表存储各类线下服务名称、基础单价、服务时长;技师信息表记录技师在岗状态、服务类别、可接单状态;预约订单表是核心数据表,存储预约类型、服务方式、预约时段、关联技师、订单状态、实付金额、结算状态;订单结算表单独留存每笔订单的结算明细、结算时间、结算方式,保证账务数据独立可追溯,避免订单数据与结算数据混淆。
技师指派是上门服务场景的核心功能,后端支持手动指派与自动指派两种模式。自动指派会优先筛选当日在岗、无时段冲突、接单量较少的技师,保证平台派单公平合理;手动指派支持管理员根据区域、技师特长人工分配订单,适配特殊服务场景需求。为防止同一时段技师被重复指派,后端会做严格的时段占用校验,从源头杜绝一单多派、服务重叠问题。下面分享后端技师自动指派核心 Java 代码:
java
/** * 订单自动匹配空闲技师 * @param serviceType 服务类型 * @param appointTime 预约时段 * @return 匹配成功的技师ID */ @Override public Long autoMatchTechnician(String serviceType, LocalDateTime appointTime) { // 查询对应服务类型、在岗可接单技师 List<Technician> techList = technicianMapper.selectOnlineTech(serviceType); if (CollectionUtils.isEmpty(techList)) { throw new RuntimeException("暂无空闲技师,请更换时段或服务类型"); } // 筛选时段无冲突技师 for (Technician tech : techList) { boolean conflict = orderMapper.checkTechTimeConflict(tech.getId(), appointTime); if (!conflict) { return tech.getId(); } } return null; }
该段代码实现了轻量化的技师自动匹配逻辑,优先筛选在岗且服务类型匹配的技师,再校验时段是否存在订单冲突,返回可用技师ID完成自动指派。代码逻辑简洁高效,无复杂冗余判断,适配中小规模线下服务平台的派单需求,同时可根据业务需求拓展距离优先、评分优先等匹配规则。
订单状态流转是保证业务闭环的关键,系统针对到店、上门两类统一设计标准化状态机。用户提交预约后订单进入待确认状态,后台指派技师后变更为待服务,服务开始后切换为服务中,服务完成后触发结算流程,订单最终变为已完成。用户主动取消、商家拒绝预约则进入已取消状态,所有状态变更均留存操作记录,方便后台追溯订单轨迹。后端严格控制状态变更权限,未完成前置流程无法跳转后续状态,避免状态错乱。
为统一管控所有订单状态变更,后端封装通用状态更新方法,统一处理参数校验与状态流转判定,核心代码如下:
java
/** * 统一更新订单状态 * @param orderId 订单ID * @param status 目标状态 * @return 更新结果 */ @Override public boolean updateOrderStatus(Long orderId, Integer status) { OrderInfo order = orderMapper.selectById(orderId); if (order == null) { throw new RuntimeException("订单不存在"); } // 禁止逆向状态流转 if (order.getStatus() > status) { throw new RuntimeException("订单状态流转异常,无法回退"); } order.setStatus(status); order.setUpdateTime(LocalDateTime.now()); return orderMapper.updateById(order) > 0; }
该方法有效避免了随意修改订单状态导致的业务漏洞,禁止订单状态逆向回退,保证每一次状态变更都符合标准业务流程。所有状态变更统一入口处理,代码统一规范,便于后期维护迭代。
订单结算模块适配线下服务完结场景,在技师确认服务完成后,系统根据预约服务项目、服务时长、附加费用自动核算订单总金额,生成结算账单。结算逻辑独立于订单主流程,避免未服务完成提前结算、重复结算问题。后端增加结算幂等性处理,同一订单仅可完成一次结算,有效防止重复扣款、重复生成账单的异常情况。
UniApp 前端针对结算场景做了适配优化,服务完成后自动拉取后端结算明细,展示基础服务费、附加费用、实付金额等信息,用户可在线确认结算、查看账单记录。前端只做数据展示与操作交互,所有金额计算、结算判定全部由后端完成,避免前端篡改价格、数据造假的安全隐患。
项目在实际开发中做了多项实用优化,适配线上部署需求。后端将热门服务、技师在岗状态等高频数据缓存至 Redis,提升多端访问速度;预约提交接口增加防重机制,避免用户重复提交同一时段预约;所有订单操作、结算操作添加事务控制,保证数据一致性;区分普通用户、技师、管理员权限,保护订单与结算数据安全。UniApp 端做了兼容性适配,解决多端样式错乱、接口请求跨端异常、适配不同手机屏幕等问题。
后台管理端支持全流程运维管理,可查看所有到店、上门预约订单,手动指派或更换技师,手动修改异常订单状态,查看每笔订单的结算明细与结算时间。同时支持服务项目管理、技师状态管控、订单数据统计,满足平台日常运营需求。
该套方案拓展性较强,开发者可基于现有基础迭代更多实用功能,比如预约超时自动取消、服务评价打分、在线支付退款、会员价格折扣、技师接单排行榜、预约消息推送等。前后端代码分层规范、逻辑清晰,适合新手学习前后端协同开发思路,也可直接落地用于家政、美容、维修、足浴等各类线下服务小程序与APP项目。
整体而言,UniApp 加 Java 后端的技术组合,非常适合线下预约服务类项目开发。本文实现的到店预约、上门技师指派、订单全状态流转、订单结算整套流程,贴合真实商业项目开发规范,解决了预约冲突、派单混乱、状态错乱、结算异常等常见开发问题。整套方案轻量化、易落地、可复用,兼具学习价值与商用落地价值。