ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Spring Boot三端产后护理系统:业务建模、权限与并发预约实践

Spring Boot三端产后护理系统:业务建模、权限与并发预约实践

每年选题列表公布的时候,“会所产后护理系统”这种题目出现的频率越来越高。乍一看,不过是一个管预约、管会员的管理系统,但真到了动手写代码那天,很多人会发现:三端(PC管理后台、护理人员移动端、客户预约端)各有各的页面,护理排期、健康档案、结算统计又横跨在中间,工程量远比想象大。这篇文章把我做基于Spring Boot的三端产后护理系统的完整思路翻出来讲透——从业务建模、技术选型、数据库设计,到接口权限、并发预约和最后的文档编写,哪些地方必须想清楚、哪些坑我已经替你踩过,都会一一交代。适合正在做同类型毕设、或者想了解Spring Boot多端项目真实开发节奏的同学参考。

1. 先看清业务:产后护理系统到底要管哪些事

1.1 会所场景下的角色与三端划分

“会所产后护理”这个业务听起来简单,实际跑起来却牵扯销售、预约、护理交付、健康跟踪、结算五个环节。如果只做几张表加几个增删改查页面,答辩十分钟就撑不住了,老师随便问一句“排期冲突怎么处理”就能让人卡壳。所以我拿到题目后的第一步不是写代码,而是先把角色画清楚,再说功能。

三端不是随便拆的,每一端对应一类真实使用者:

  • 管理端(PC网页后台):店长或管理人员使用,维护员工信息、服务项目、价格策略,查看订单流水、营收统计,审核和处理异常预约。
  • 护理人员端(移动H5页面):护理师在手机上查看今日待服务列表、接单、执行护理、回填服务记录和客户健康指标。
  • 客户预约端(移动H5页面):产后妈妈注册登录后,浏览服务项目、预约护理时间、查看个人健康档案和历史订单。

角色定位理清之后,功能边界就自然划开了。最容易犯的错,是把管理端做得又大又全,护理端只是管理端的手机版——这等于没按业务设计系统,答辩时很难解释“为什么需要三端”这个问题。真正合理的做法是每端只保留本角色最常用的操作,界面密度、字段数量、交互路径都要跟着角色走。

1.2 从“护理流程”倒推功能清单

功能清单我不喜欢拍脑袋列,而是沿一条业务主线推出来:客户到店建档 → 预约护理项目 → 护理师接单 → 服务执行 → 回填健康数据 → 客户确认 → 结算。沿着这条线,一个能打的系统至少包含以下模块:

  • 客户建档:姓名、年龄、生产方式、产后天数、过敏史、基础健康指标,这些是后续服务推荐的数据基础。
  • 服务项目管理:服务名称、时长、价格、适用阶段、所需护理师等级,支持上下架和套餐组合。
  • 预约管理:选择服务项目、期望时间段、指定护理师,系统做冲突校验和状态跟踪。
  • 工单与执行:预约确认后自动生成护理工单,护理师按单执行,完成后回填服务结果。
  • 健康档案:每次护理后的体重、腹围、伤口恢复情况、情绪评分等指标,按时间轴展示变化趋势。
  • 订单与结算:预约关联订单,记录支付状态,管理端能按时间段统计营收。

这套清单走下来,基础表至少七八张,接口五十个起,前端页面二十多个,才配得上“三端系统”这个体量。如果你做完发现只有四五张表,大概率是业务理解缺了环节,建议回头补需求分析。

2. 技术选型与整体架构:为什么这样搭最稳妥

2.1 后端与数据库选型

后端选Spring Boot几乎是这类题目的标准答案,理由很实在:生态成熟,网上资料多,卡住时容易查到解法;自动配置让项目搭建成本极低,一个空工程几分钟就能跑起来;内置服务容器,打jar包直接部署,演示时不用折腾服务器环境。

持久层我选MyBatis-Plus,单表操作用内置方法,多表关联写XML,既有灵活性又减少样板代码。数据库用MySQL 8.0,存储引擎InnoDB,字符集一定要用utf8mb4,别用utf8。客户姓名里有生僻字或者备注里有特殊符号时,utf8会直接报错,演示现场出这种问题非常尴尬。

Redis在这个项目里的定位要克制。网上很多教程把Redis当万金油,什么数据都往里塞,答辩时反而容易被追问“这里为什么必须用Redis”。我的建议是只做三件事:存登录态的Token、给预约时间段加分布式锁、缓存服务项目列表这类变更极少的热数据。定位清晰,代码也干净。

2.2 三端前端的取舍

管理端做PC网页,技术栈用Vue配合一套成熟的基于Vue的后台管理脚手架。这类脚手架自带登录页、侧边栏、表格和表单组件,省下的时间足够把业务页面打磨细致。要注意别被模板带着走,菜单结构要按护理系统的业务组织,而不是保留模板默认的布局。界面顶部换成系统名称和自定义图标,侧边栏只留本项目模块,这些细节在演示时一眼就能看出有没有走心。

护理人员端和客户端我统一做成移动端H5页面,放在手机浏览器访问。为什么不拆成两类不同的移动端技术方案?因为毕设周期内多端原生开发的工作量太夸张,而且演示时还要现场装环境,风险大。移动H5一套代码两处复用,差异只体现在菜单和接口权限上,这个取舍在答辩时完全讲得通。

前后端交互统一走RESTful接口,约定返回格式为code、message、data三件套。我习惯每写完一个接口就把参数和示例值维护进在线接口调试工具,后面写论文的接口设计章节时直接截图,省一大半时间。接口命名也统一用资源名加动作的方式,比如预约相关就是appointment/create、appointment/cancel,看名字就知道干什么。

3. 数据库设计:核心表结构与关键字段取舍

3.1 会员、员工、服务项目三张基础表

数据库设计决定这个项目是“看着完整”还是“真的能跑”,先把三张基础表说清楚。

会员表是整个客户端的根。除了姓名、手机号、年龄这些常规字段,我建议重点设计三个业务字段:生产日期(用于计算产后天数,判断适合哪些服务项目)、健康评分(由护理师在服务回填时更新)、建档时间。产后天数别存成数字,存生产日期,需要时用日期计算,业务规则变化时不需要改表。比如新增“产后30天内推荐某套餐”的规则,代码里判断就行,表结构不用动。

员工表要能区分职位,我加了一个position字段:店长、前台、护理师、财务,不同职位对应三端里不同的操作权限。护理师还需要关联擅长项目,这里用一张中间表employee_service维护多对多关系,否则“某个护理师不支持某项服务”的校验就没法做。

服务项目表有个容易忽略的细节:价格字段不能只存当前价格,要同时设计原价和会员价两个字段。后面做套餐优惠或会员折扣时,没有这两个字段就得改表结构,毕设演示期间改表是件很麻烦的事。再加一个status字段控制上下架,下架的项目不影响历史订单查询。

3.2 预约与护理工单的状态流转设计

预约表和工单表是这套系统里业务复杂度最高的两张表,状态设计得好不好,直接体现有没有真实项目经验。

预约表我设计了五个状态:待确认、已预约、服务中、已完成、已取消。客户提交预约后是待确认;护理师确认接单后变成已预约;点击开始服务变成服务中;服务完成并回填记录后变成已完成。每个状态变更都记录变更时间和操作人,这就是审计字段的雏形,写进论文是实打实的加分项。

工单表把一次护理交付固化成一条记录:关联预约ID、关联护理师ID、服务开始结束时间、客户到场状态、服务备注。工单一经完成,不允许物理删除,只能走异常作废流程。很多人不理解这条规则,但答辩老师问“数据录错了怎么办”时,你能说出“业务单据走状态调整而不是物理删除”这个答案,已经和只会做增删改查的人拉开差距了。

这两张表的关联关系也要提前定好:预约先于工单存在,工单由预约状态流转触发创建。我见过有同学把两张表合并,结果要么预约信息缺失要么工单记录冗余,后面统计怎么都对不上。分开设计,各自负责一段业务状态,边界清楚,代码也更好写。

4. 接口与权限:三端共用一个后端怎么做到互不串门

4.1 基于JWT的多角色认证

三端共用一个后端,最怕的是权限混乱:客户调了管理员的接口、护理师看了不该看的预约数据。解决办法是统一走JWT认证加角色权限拦截。

登录接口验证用户名密码后,根据用户类型(客户、员工、管理员)签发不同的Token,Token里带上userId、role、terminal三个信息。后端写一个全局拦截器统一解析Token,再结合接口上的权限注解判断当前角色能不能访问。管理端接口放在/admin路径下,客户端接口放在/client路径下,护理端放在/staff路径下,路径前缀本身就先做了一层物理隔离,拦截器是第二层。

实际操作中发现一个很实用的拆分:登录接口三端可以共用,但注册接口必须拆开。客户是自助注册,字段是姓名、手机号、密码;员工账号是管理端后台统一创建,字段是工号、职位、初始密码。两者字段不同、流程不同,硬塞进一个接口会让前端逻辑非常别扭。我在项目里把登录统一成一个接口,注册拆成clientRegister和employeeCreate两个,实际用下来干净很多。

另外,Token有效期要分开设置:客户端和护理端设成7天,管理端设成2小时。管理端是后台操作,短期过期更安全;移动端频繁过期会严重影响演示体验。这个细节虽然小,但答辩时主动讲出来,能体现你考虑过真实运营场景。

4.2 预约冲突与并发处理

预约模块是整个项目里最容易出bug的地方。典型场景:两个客户同时选中同一个护理师的同一个时间段,两边几乎同一秒提交,如果代码是先查再插,两个请求都会查到“无冲突”,结果都插入成功,护理师当场分身乏术。

我的方案是双保险。数据库层面,给预约表加联合唯一约束,把护理师ID、服务日期、时间段三个字段设成联合唯一键,重复插入直接报错。应用层面,在插入预约前用Redis分布式锁对护理师当天的时间段加锁,锁的key设计成schedule:{employeeId}:{date},拿到锁之后再做冲突校验和插入,处理完释放锁。

正常情况下,分布式锁已经把并发请求都串行化了,基本不会走到数据库唯一约束那一步;万一锁覆盖不到的极端场景,唯一约束兜底,捕获到重复键异常后提示用户重新选择时间段。我在本机用并发测试工具模拟了同时提交预约的场景,双保险下没有出现过重复数据。这个方案实现成本不高,讲起来逻辑顺畅,属于性价比很高的设计点。

5. 最容易翻车的五个细节

5.1 时间处理与日期展示

三端系统一定会碰到时区、格式、跨天预约三个问题。我的经验是:后端统一存时间戳或标准DATETIME,接口传输统一用时间戳字符串,前端只负责展示格式化,不做时间计算。这样手机端、电脑端、不同浏览器看到的都是同一时刻,不会出现“前端少传8小时”这种时区笑话。

跨天预约更坑。有人把“日期”和“时间段”拆成两个字段,比如date=2025-06-18、slot=09:00-10:00,一旦服务开始时间是晚上十点,跨过零点,判断条件就复杂了。我建议服务排期表只存“服务开始时间+服务时长”,结束时间由后端统一计算。这样即使预约跨天,逻辑上也只是一个连续时间区间,判断冲突时直接比较时间戳范围即可。

还有一个容易被忽略的点:列表查询的默认时间范围。预约列表默认加载最近7天就好,别一次把全表数据拖出来,数据量一大页面就卡。我第一次做的时候图省事直接查全部,等到演示时加载了上万条记录,页面转圈转了五秒,差点现场翻车。

5.2 图片上传与文件存储

客户头像、健康记录图片、服务项目宣传图,这些功能绕不开图片上传。我最初图省事把图片存进数据库的BLOB字段,结果列表接口越跑越慢,一张图片几十KB还好,到了几百KB就明显拖速度。后来改成文件存储方案:上传接口把文件写到服务器指定目录,数据库只存相对路径,通过映射路径读取图片,列表接口只查路径字符串,速度立刻正常了。

文件类型校验也踩过坑。只判断扩展名完全不够,有些人把exe改成jpg后缀就能绕过,稳妥的做法是同时校验文件头,也就是所谓的魔数。我写了一个工具方法,读取文件前几个字节判断真实类型,不是图片直接拒绝。这套校验既防恶意上传,也防前端传错格式,属于必须补上的步骤。

另外一个容易被忽略的点是文件重命名。存文件时不要用原始文件名,一是中文名在URL里容易乱码,二是重名会覆盖。我用UUID加时间戳重新命名,路径按日期分目录存储,比如upload/2025/06/18/xxx.jpg,后面做清理和排查都方便。

5.3 事务与支付状态

订单生成涉及多张表写入:预约表、订单表、支付记录表,必须用事务包起来,任何一个环节失败都要整体回滚,否则就会出现“预约创建成功但订单不存在”这种脏数据。Spring里加一个@Transactional注解很简单,但有一个坑必须知道:事务方法不能在同一类内部通过this调用,否则注解会失效。原因是Spring的事务是基于代理对象实现的,this调用走的是原始对象,代理逻辑没生效。这个知识点我建议背下来,答辩被问到的概率很高。

支付环节做不了真实支付,一般用模拟支付流程:客户提交订单后进入待支付状态,点击确认支付按钮,系统在支付记录表插入一条模拟支付成功记录,再把订单状态置为已支付。注意状态流转要单向:待支付到已支付、已支付到已退款,不能随意跳状态,更不能从待支付直接到已退款,否则月末统计营收时数字会对不上。

我还加了一个定时任务兜底:超过30分钟未支付的订单自动取消,并把释放的时间段还给预约池。这个功能代码不多,但演示时能展示“过期订单自动撤销”这个场景,非常加分。

6. 毕设文档与代码讲解:怎么让答辩老师一眼看懂

6.1 系统设计说明书的结构

程序写完了,文档才是决定分数的关键。我习惯的结构是:需求分析、可行性分析、系统设计、数据库设计、系统实现、系统测试。结构不需要花哨,关键是每一章要能自圆其说。

需求分析章节放用例图,把三端的核心用例列清楚,每个用例既要写主流程也要写异常流程。比如预约用例,主流程是选项目、选时间、提交;异常流程是所选时间段已被占、护理师不支持该项目、客户约了自己所在时段冲突。把这些写出来,说明你是认真推演过业务的。

数据库设计章节放ER图和每张表的字段说明。字段说明的备注一定要写清业务含义,比如status=1 代表已预约、2 代表服务中,而不是只贴一张建表SQL。很多同学栽在这里:表建得不少,但老师问某个字段什么含义,当场翻代码找半天。系统实现章节配合核心功能截图,截图按业务流程顺序截,从登录页开始,按主线一步步截到最后的结果展示页,而不是想到哪截到哪。

6.2 代码讲解的演示逻辑

代码讲解的要点是讲流程,不是讲语法。老师不会逐行看代码,但一定会问“从登录到预约这条链路是怎么走的”。所以我讲解时固定用一条主线:客户注册 → 登录获取Token → 浏览服务项目 → 提交预约 → 护理师接单 → 回填健康记录 → 客户查看档案。

每走到一个环节,打开对应的Controller、Service、Mapper三层,讲清楚前端调了哪个接口、接口做了什么校验、数据写进了哪张表。三层代码顺着捋一遍,老师对你的代码水平就有了整体判断。讲完主线之后,我会挑两个亮点专题展开:一个是预约并发处理里Redis锁如何工作,另一个是健康档案模块如何按时间轴聚合展示数据。这两个点讲透了,足够证明这个系统不是纯增删改查。

演示时的操作顺序也建议固定:先开数据库客户端,再启动后端,最后打开前端页面,每一步的执行结果都让老师看到。不要一上来就切到已经开好的页面,那样老师会怀疑你提前动了手脚。整个过程控制在8到12分钟,讲完主线留几分钟专门应对提问。

7. 拿到源码后的定制方向:怎么把它变成“自己的作品”

7.1 二次开发的正确顺序

不管从哪个渠道拿到源码,我的建议都是不要原样提交,先做一轮二次开发。顺序分三步:第一步,把包名、项目名、数据库名全部改掉,这一步工作量不大但必须做;第二步,加一个别人没有的独立小功能,比如护理知识库、客户满意度回访、服务套餐组合,这些小模块和主流程解耦,加进去不会破坏原有结构;第三步,把界面标题、顶部图标、配色方案换成自己的,移动端H5的登录页和首页是最容易被看出定制痕迹的地方,优先改。

改包名看着简单,实际操作时要注意等配置文件、Mapper扫描路径、前端接口地址里的对应关系。我建议用开发工具全局替换,替换后跑一遍全量测试,确认列表查询、登录、预约三条链路都正常再交。

7.2 常见定制点的实现思路

如果老师要求“和参考系统有明显区别”,最快的突破口在统计报表。原系统可能只有订单列表,你可以加一个管理端的营收看板,按日、周、月展示营收趋势图,再按服务项目统计占比。技术实现不复杂,前端引入图表组件,后端写几个带时间段参数的统计接口,用分组查询按日期和项目聚合金额。视觉效果提升明显,答辩时还能顺带讲“我是如何设计聚合查询的”,属于性价比极高的定制项。

另一个好改的点是消息通知。增加一张站内消息表,字段包括接收人ID、消息类型、内容、是否已读、创建时间。在工单状态变更的代码位置插入消息写入逻辑,比如护理师点击“开始服务”时,给客户推一条“您的护理师已开始服务”,客户端做一个消息列表页面,未读数在底部导航栏显示红点。改动范围小,业务闭环完整,演示效果好,老师问起来你也能讲清楚表结构和触发时机。

8. 从失败里换来的经验:几个最容易让毕设翻车的习惯

8.1 环境与部署的坑

毕设演示最怕环境崩。我见过不止一次有人在讲台上发现后端启动失败,原因是MySQL字符集没配、端口被占用、JDK版本不对。建议提前整理一份部署文档,写明JDK版本、MySQL版本、Redis是否必需、启动命令,然后按文档从零部署一遍。换一台电脑、换一个网络环境,确保能在十分钟内重新跑起来,才算真正准备好演示。

启动失败最常见的三个原因:数据库连接配置写错了地址或密码、Redis服务没启动、前端构建产物路径不对。这三个问题我都遇到过,建议在部署文档里用醒目的方式标注“先检查这三个地方”。答辩现场时间紧张,能第一时间定位问题是最大的加分项。

8.2 答辩演示的预演

演示不要跳着操作,按业务主线一步步走。提前准备两套测试数据:一套正常数据用于主流程演示,包括几个已完成预约、几条健康记录、几笔已支付订单;一套边界数据用于回答“如果……会怎么样”的问题,比如一条已取消的预约、一个没有权限的账号、一个已经被占用的时间段。老师问任何异常场景,你都能现场操作验证,比口头解释有说服力得多。

每次预演都记录一下时间,控制在8到12分钟最合适。超过15分钟老师会不耐烦,少于5分钟又显得内容单薄。我自己的习惯是预演三遍:第一遍看流程通不通,第二遍调讲解节奏,第三遍让同学扮演答辩老师随机提问,把可能被问到的追问点提前想好答案。准备到这个程度,上场基本不会慌。

说了这么多,最核心的体会其实就一句:毕设系统不追求技术多花哨,追求的是业务闭环完整、链路讲得清楚、每个设计决策都经得起追问。把三端定位、预约并发、状态流转、文档结构这几件事想透,这套基于Spring Boot的产后护理系统就真正成了你自己的东西。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进