最近帮一个朋友看了一套“基于人脸识别的智慧医疗预约挂号平台系统”的完整项目包,包含源码、配套设计文档、部署文档和讲解材料。这类项目在毕业设计和课程设计里非常常见,几乎是医疗信息化方向绕不开的一个经典实战题。标题看着很长,但拆开其实就是三件事:预约挂号业务、人脸识别身份认证、配套管理后台。今天我就以这套项目为例子,把从需求拆解、架构设计、核心模块实现,到环境部署和排坑的完整过程捋一遍,希望能给正在做类似系统或者准备复现项目的同学一点实际参考。
我接手过不少这类“全家桶”项目,最大的感受是:大多数人拿到源码后第一反应是急着启动,结果卡在环境、依赖、摄像头调用这些地方,真正理解业务逻辑的时间反而没剩多少。所以这篇文章不打算只讲怎么“跑起来”,我会把每块设计背后的为什么也讲清楚,包括为什么选这个方案、参数怎么调、哪些坑是必踩的。内容偏向实战,适合准备做医疗类系统设计的人、想练手全栈项目的开发者,以及需要快速消化一套陌生源码的朋友。
1. 先拆解核心需求:这个平台到底要解决什么问题
1.1 传统挂号流程的痛点
挂号这件事,很多人觉得不就是排队或者手机点一下吗?但放在医院场景里,问题比想象中多。线下的情况:窗口排队时间长,患者早上六点到医院大厅,排到窗口可能号就没了;好不容易挂上号,取号、候诊、签到、就诊,每个环节都要掏身份证或者就诊卡,忘带就只能再跑一趟。线上的情况:虽然有了在线预约,但身份核验环节很弱,很多平台只是靠手机号加验证码,号贩子可以囤一批账号抢热门专家号再高价转卖,患者拿别人身份证冒名就诊的情况也时有发生。
这些痛点的本质其实指向同一个问题:医疗场景需要一种更可靠、更自然的身份确认方式。密码可能忘记,二维码可能截图转发,身份证可能忘带,但人脸是和本人绑定的,不需要额外携带任何凭证。所以把生物识别引入挂号流程,不是炫技,而是医院真实存在的需求。
1.2 人脸识别进入医疗场景的价值
人脸识别在这个系统里承担的角色,可以理解成“无感通行证”。患者在注册时完成一次人脸录入,之后登录、挂号、取号、签到这些环节都可以刷脸完成。这样做的好处有几个。
第一个是防冒用。人脸特征很难被他人复制,黄牛囤号之后没法冒用原主身份去就诊,因为每次就诊签到时还要做人脸比对,比对不通过就进入不了流程。第二个是提效率。传统窗口核验身份靠工作人员肉眼比对证件照和本人,速度慢、准确率不稳定,换成算法识别之后,单次比对的耗时可以控制在几秒甚至更短。第三个是留痕。每次刷脸都会产生一条操作记录,后台可追溯,出了问题可以查证。
需要明确的是,人脸识别并不是要把人工完全替换掉,而是把原来需要“主动出示证件、人工判断”的环节,变成“自然站到摄像头前、算法辅助判断”。这种思路在医疗信息化里叫身份核验前置,本质上是把安全性和便捷性同时往上提了一档。
1.3 角色与核心业务链路
一个完整的预约挂号平台,至少要覆盖三类角色:患者、医生、管理员。患者是系统的使用主体,完成注册、挂号、取消、查询;医生负责出诊排班、查看预约名单、接诊时核验患者身份;管理员维护科室、医生信息、号源配置、数据统计。说白了,患者端和管理后台是支撑业务运转的正反面,医生端则负责把预约单转化成实际就诊记录。
核心业务链路并不复杂:患者注册并绑定人脸,然后登录系统,选择科室和医生,再选择有空余号源的时段,提交预约形成订单,就诊当天通过人脸核验完成签到。注意,预约挂号不是“付款就结束了”,它后面的状态流转才是系统的难点。一次预约至少要经历待支付、已支付、已取消、已完成这几个状态,每个状态的切换都要有严格的规则限制,比如已取消的号源要回补、迟到的号要释放、退号有次数限制等等。很多人复现这类项目只关注界面显不显示,恰恰忽略了状态的闭环,所以我建议拿到源码先别急着跑,而是把订单状态的流转画出来,这比界面重要得多。
人脸识别在这个链路里嵌了两个关键节点:登录节点和就诊核验节点。登录节点负责确认“你是谁”,就诊核验节点负责确认“你就是这个预约单对应的本人”。两个节点一个管入口,一个管出口,都是不能跳过的环节。
2. 系统架构与技术选型解析
2.1 整体架构:前后端分离加识别模块
这套系统的整体架构可以概括为“前端 + 后端服务 + 数据库 + 人脸识别引擎”。前端负责用户交互,后端负责业务逻辑和数据处理,数据库负责持久化,人脸识别引擎独立承担检测、特征提取和比对的职责。
为什么要把人脸识别拆出来单独做?因为它的技术栈和业务后端不一定相同。业务后端可能是 Java 写的,而人脸识别部分通常依赖 Python 的计算机视觉库,强行塞进同一个进程里会带来依赖冲突和部署复杂度。拆出来之后,业务服务通过接口调用识别模块,模块内部无论用 OpenCV、dlib 还是云 API,都不影响主体业务,后面想换方案也好换。
前后端分离也是同样的道理。前端用 Vue 或者小程序承载页面,后端只提供 JSON 接口,两者通过 HTTP 通信。这样做的直接好处是:开发可以并行,前端调接口、后端写逻辑互不阻塞;部署也更灵活,前端静态文件可以扔在 Nginx,后端独立跑在服务器端口上。对于毕业设计或者简历项目来说,前后端分离本身就是一个可以展开讲的架构亮点。
2.2 技术栈怎么选
我见过的主流选择有两种路线。
第一种是 Java 路线:后端用 Spring Boot,搭配 MyBatis 或 MyBatis-Plus 操作数据库,前端用 Vue + Element UI。这套组合的优点是资料多、社区活跃、问题好搜,而且 Spring Boot 的自动配置能省掉大量 XML 配置。缺点是对环境要求稍高,JDK、Maven 这些版本匹配不对就会出幺蛾子。
第二种是 Python 路线:后端用 Flask 或 Django,前端同样可以配 Vue,人脸识别模块可以和后端写在一起,因为整个项目都是 Python,依赖统一管理更省事。这套组合的好处是和人脸识别的库串联最顺畅,坏处是大型业务模块的开发规范程度不如 Java 生态,尤其涉及高并发时会费劲一些。
我的建议很直接:如果主要诉求是快速跑通并便于讲解,选 Python 路线会顺手很多;如果目标是展示工程化能力、准备往企业开发方向走,选 Spring Boot 路线更有说服力。具体到一套现成源码,换技术栈不现实,关键是理解当前代码走了哪条路,别硬把两套思路混在一起改。
人脸识别引擎方面,本地方案通常依赖 OpenCV 的 Haar 级联检测器加人脸特征模型,或者用 dlib 库的 HOG 检测、人脸关键点定位和特征描述子。更省心的做法是直接用封装好的开源库,比如 face_recognition,它底层调的还是 dlib,但接口封装得对人友好很多,几行代码就能完成特征提取和比对。
2.3 人脸识别方案横向对比
很多人在选型时最纠结的就是人脸识别方案,下面这张表我做过多次对比,基本覆盖了常见选项。
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| OpenCV 基础检测 | 完全离线、依赖少、代码透明 | 特征提取和比对要自己写,精度一般 | 原理演示、教学、对精度要求不高的场景 |
| dlib + face_recognition | 离线可用、接口友好、精度不错 | dlib 编译安装麻烦、单张特征提取速度一般 | 本地部署、毕设项目、中小规模比对 |
| 云 API 人脸识别 | 精度高、自带活体检测、维护成本低 | 需要联网、按调用量计费、数据出本地 | 企业级系统、对安全等级要求高的场景 |
选方案的时候一定要考虑答辩或讲解时的处境。用云 API 的优点是效果好,但遇到“底层原理是什么”这种问题就比较难展开。用本地方案,虽然精度稍微逊色,但每一步检测、特征点定位、相似度计算都能讲清楚,反而更容易拿到分。
还有一个关键点:活体检测。如果只做静态人脸比对,一张照片就能骗过系统。正规场景至少要加入简单的动作活体检测,比如随机要求用户眨眼睛、张嘴巴、左右转头,通过动作序列判断摄像头前的是真人还是照片。有些开源性项目会省略这一步,但实际部署时几乎必问,所以复现时能加尽量加上。
3. 核心模块实现与数据库设计
3.1 患者端:从注册到完成挂号
整套系统里,患者端的流程最复杂,它串起了账号体系、人脸模块和预约业务。
先看注册登录。正常的流程是填写手机号、密码等基础信息注册账号,然后进入人脸绑定环节。人脸绑定不是简单拍一张照片存下来,后端需要对人脸区域进行检测,确认画面里确实有人脸,然后提取特征向量,再把这个特征向量保存到当前账号的记录里。登录时可以保留“账号密码登录”和“刷脸登录”两种方式,刷脸登录的逻辑是:摄像头抓拍一张照片,提取特征,拿这个特征去人脸特征表里做 1:N 搜索,找到最相似的那个用户,直接把会话登录为该用户。
这里要提醒一个设计细节:1:N 搜索要设置相似度阈值。阈值设得太低,任何人都能登录别人的账号;设得太高,本人换个角度就识别不出来。一般根据实际测试调,比如余弦相似度 0.75 以上才允许登录,也可以放宽到 0.7,具体看测试环境的光线和摄像头。稳妥的做法是在阈值不确定时,先跑一批自己的正负样本来观察分布,再倒推阈值。
预约挂号的流程,就是从患者端选择科室开始。科室通常按“内科、外科、儿科这样的分类展示”,进入科室后展示医生列表,每个医生下面会挂这个月的排班表。号源的设计一般有两种:固定总量和分时段号源。开始时间、结束时间、每个时段最多挂号人数,这些信息都来自医生排班表。患者点击某个时段,系统先检查当前已预约数量是否达到上限,没满就生成一条待支付或直接成功的预约单。提交完成后,号源数量需要立即更新,否则会出现很多人同时抢一个时段的超卖问题,这一点我在第 5 章会详细讲。
3.2 人脸识别模块的落地细节
这块是整套系统最容易被问细节的地方,我拆开讲。
第一步是人脸检测。说白了就是告诉算法“这张图片里哪个区域是脸”。OpenCV 的 Haar 级联分类器是一个经典方法,原理是通过滑窗方式扫描图像,在每个窗口上用训练好的特征判断是否存在人脸。速度快但容易受光照、角度影响。dlib 的 HOG 检测器对新版本 dlib 来说替代了旧的人脸检测模型,鲁棒性更好。如果人脸部分不清晰,可以加一步人脸对齐,把五官位置统一校准到标准位置后再提取特征。
第二步是特征提取。这里要明确“人脸特征不是一个数,而是一串向量”。传统方法提取的是手工设计特征,现在是深度学习网络输出一个高维特征向量,通常 128 维或 512 维。face_recognition 库加载训练好的模型,输入人脸图像区域,输出 128 维的特征向量。这个向量的含义是把空间上相似的人脸映射到相近的区域,比对时计算欧氏距离或余弦相似度就行。
第三步是特征存储。128 维的向量可以序列化成字符串存入数据库的 text 字段,也可以存成 BLOB 二进制对象。每次比对时,更新当前用户的目标特征与数据库中所有历史特征逐一计算相似度。如果用户量不大,几千条记录直接全表扫也没多大压力,量大再考虑引入向量数据库。
第四步是活体检测。这个必须单独说。方案分两类:动作活体和红外活体。经典的动作活体实现方式,是人脸检测成功后,系统随机生成一个动作指令,比如“请眨眼”,然后连续采集几帧图像,判断眼睛是否完成了一次闭合再睁开的动作。红外活体依赖硬件设备,通过红外摄像头区分真人皮肤和屏幕图像,成本高但防攻击能力强。作为项目,实现动作活体已经足够。
3.3 医生端与管理端
医生端的功能相对克制,核心是“排班”和“核验”。医生登录后台后可以设置自己未来若干天的出诊时间,比如“每周一上午、周三下午出诊”,系统会根据这个配置自动生成号源。患者预约的订单会汇集到医生的接诊列表,列表里能看到时间段、患者姓名、预约状态。就诊开始时,医生可以点击“开始核验”,调用摄像头对当前患者做人脸比对,确认患者和预约单持有人一致。
管理端就是数据治理的地方。科室管理负责维护科室分类和排序,医生管理负责添加上下文信息,比如职称、擅长方向、出诊价格。号源配置是管理端的重点,管理员可以调整某个医生某天的号源总量和放号时间。统计功能一般会包含每日挂号量、各科室热度、退号率这些指标,简单实现就是用 SQL 做聚合统计。
很多人在复现项目的时候只盯着患者端好看不好看,医生端和管理端草草带过,结果答辩时被问到“医生怎么用这个系统”就卡住了。其实医生端和管理端才是体现系统完整性的地方,哪怕界面朴素一点,功能闭环了才像一个能落地的产品。
3.4 数据库设计要点与预约状态机
数据库设计我建议重点看这几张表:用户表、人脸特征表、医生信息表、科室表、排班表、预约记录表。
用户表是最基础的,包含账号、密码、姓名、手机号、角色,以及就诊相关的字段。人脸特征表的关键字段是 user_id、特征向量、录入时间、状态,一个用户可以对应多条特征记录,比如换手机后重新录入。医生表区别于用户表,它要额外存所属科室、职称、简介、挂号费这些扩展信息。排班表是生成号源的关键,字段包括医生 ID、出诊日期、开始时间、结束时间、总号量、已约号量。预约记录表就是订单表,字段包括患者 ID、排班 ID、预约时段、状态、创建时间、支付状态。
预约状态机是整个业务实现里最容易写乱的部分。我建议至少定义五个状态:待支付、已支付、已取消、已过期、已完成。待支付和已支付之间的转换依赖支付回调,为了演示方便,很多系统会把“提交即成功”作为默认逻辑,即支付状态默认为已支付,这块要看清源码里的设定。已取消的预约单要回补号源,即排班表的已约号量减一。已过期状态用于处理就诊当天没来也没有取消的订单,需要定时任务扫描处理。已完 成状态则在医生核验通过后触发。
4. 从源码到本地跑通:部署实操记录
4.1 环境准备
拿到一个没有接触过的源码包,第一步永远是确认环境要求。一般部署文档里会写清楚,但很多时候文档版本过期,需要自己判断。我先列一套常见组合:
- JDK 1.8 或更高(Java 后端常见要求)
- MySQL 5.7 或 8.0
- Node.js 14 以上(前端项目需要)
- Python 3.8 以上(人脸识别模块如果是独立服务)
- Maven 3.6 以上(Java 后端构建工具)
装环境的时候要注意版本匹配。比如 Spring Boot 2.x 通常搭配 JDK 8 或 11,换到 17 可能出现兼容问题;Node 版本太新时,旧的前端项目编译会报 OpenSSL 错误。我习惯先建一个虚拟机或者用 Docker 装一套固定环境,避免污染日常使用的主机。
4.2 数据库初始化和配置文件
数据库这块最标准的动作是:启动 MySQL,用 root 登录,执行CREATE DATABASE创建项目数据库,然后导入项目提供的 .sql 脚本。导入的时候指定字符集为 utf8mb4,否则中文数据容易变成乱码。
导入完成后要检查一下表是否建全,尤其是那些带时间字段、状态字段的表。接着修改后端配置文件。如果是 Spring Boot 项目,主要改 application.yml 或 application.properties 里的数据源配置;如果是 Python 项目,很可能改 config.py 或者 .env 文件。需要确认的关键项包括数据库地址、端口、用户名、密码、以及人脸识别模块调用的接口地址。
一个容易踩的坑是 MySQL 时区。配置文件里的连接串如果不加serverTimezone=Asia/Shanghai,Java 驱动可能报时区错误。另一个坑是 MySQL 8.x 默认的认证组件是 caching_sha2_password,老版本的 JDBC 驱动连不上,需要把驱动换成对应的新版或者改用 mysql_native_password。
4.3 后端与前端启动
后端启动相对简单。Spring Boot 项目在项目根目录执行mvn spring-boot:run,或者先mvn clean package打成 jar 再java -jar运行。Python 项目则先装依赖,在 requirements.txt 所在目录执行pip install -r requirements.txt,然后运行入口文件。启动后先看日志,确认端口有没有被占用、数据库连接有没有成功。
前端部分通常是 Vue 项目。进入前端目录后执行npm install装依赖,这个过程可能会很慢,最好配置一下 npm 镜像源。装完运行npm run dev,正常会在本地某个端口启动,比如 8080。这时打开浏览器访问前端页面,会发现页面能加载但接口报错,原因大概率是跨域问题。前端开发环境的解决办法是配置 Vite 或 webpack 的 devServer proxy,把/api开头的请求转发到后端地址。这一步几乎每个项目都要做,不会调代理就手动把后端接口地址改成允许跨域也行,但正规做法是走代理。
4.4 摄像头与人脸识别的本地调试
人脸识别功能在本地跑通之前,先要做一个小验证:单独跑一个测试脚本,用本机摄像头抓取一张图片,检测人脸并输出特征向量。这样能确认摄像头驱动正常、检测算法正常、特征提取正常,之后再接入业务系统,排查问题范围会小很多。
浏览器调用摄像头有安全限制,只有 localhost 或者 HTTPS 环境下才能调起 getUserMedia。如果你的前端页面是用局域网 IP 访问的,摄像头可能直接报错。解决办法是在本地调试时用 localhost 访问,真要部署到服务器就配 HTTPS。还有摄像头被其他程序占用的问题,比如钉钉、微信、腾讯会议占用了摄像头,浏览器再调就会失败,调试时把后台占用摄像头的程序关掉。
人脸识别模块如果独立成一个 Python 服务,需要保证它在后端启动前已经跑起来,否则业务后端调用识别接口时会连接失败。排查时可以直接用 curl 调用识别服务的健康检查接口,先确认服务本身是活的。
5. 实战避坑:调试中的典型问题与排查思路
5.1 人脸识别相关的高频问题
人脸识别模块是整个系统里出问题最多的部分,而且问题往往和环境强相关。
dlib 安装失败是我见过最高的坑。Windows 上直接pip install dlib经常会因为缺少 CMake 和 Visual Studio Build Tools 而编译失败。解决办法是先去装对应版本的预编译 wheel 包,或者用 conda 安装编译好的 dlib,这样能省掉大量编译时间。如果项目里用的不是 dlib 而是 OpenCV,也要注意 OpenCV-contrib-python 和 opencv-python 不要混装。
摄像头黑屏也经常遇到。出现黑屏先分两步排查:第一步看浏览器控制台有没有权限报错,有权限报错就去设置里允许摄像头;第二步看有没有别的程序占用摄像头,全部关掉再刷新页面。还有一个容易被忽略的点是,后端人脸识别服务如果跑在远程服务器上,而远程服务器本机没有摄像头,那测试人脸录入就会一直失败。这种情况应该在前端本地设备完成图像采集,把图片文件传给后端做特征提取,而不是让后端直接调用摄像头。
识别准确率不稳定是另一个高频问题。影响最大的三个因素是光照、角度和模糊。解决方案是录入阶段做人脸检测质量判断,光线差的场景通过 io 方式提示用户移动到光线充足的位置。比对阶段可以适当引入人脸对齐,把眼睛、鼻子、嘴巴对齐到标准位置后再提特征,能显著提升准确率。相似度阈值也可以做成可配置项,放到配置文件里,方便根据现场环境微调。
活体检测被静态照片绕过的问题,在用了人脸识别的系统里属于致命伤。如果代码里只有简单的 “检测到人脸就算通过”,哪怕加上了第三方活体 API 但没做前端配合,也可能被绕过。建议至少实现动作随机指令,且每次动作从集合中随机选择,避免固定动作被录制视频诈骗。
5.2 数据库与业务逻辑的坑
数据库层面,中文乱码问题大多出在连接串和表结构两处。连接串没指定 utf8mb4、表默认字符集是 latin1 或 utf8,都会导致中文显示异常。修改之后记得要重建表或者把已有表 CONVERT TO CHARACTER SET utf8mb4。
并发超卖问题属于预约类系统的通病。简单实现是“先 select 已约数量,判断是否小于总数,再 insert 预约记录”,这个逻辑在单用户下没问题,但并发请求打过来时会同时读到同一个旧值,导致号源被超卖。解决办法有两种:一种是在排班表加 version 字段,用乐观锁控制更新;另一种是更新时直接加条件UPDATE schedule SET booked = booked + 1 WHERE id=? AND booked < total,受影响行数为 0 就说明号源已被抢完。第二种方案更简单,推荐优先使用。
预约取消的号源回补也容易忽视。很多人只写了“取消预约”接口把订单状态删掉或改成取消,但没有同步更新排班表的已约号量。结果就是号源永久少一个,看起来一直被占着。下一章的源码阅读环节我会专门提醒看这个逻辑是否正确。
前后端跨域与 token 失效也很常见。跨域问题可以通过后端 CORS 配置或者前端代理解决。token 失效一般是登录拦截逻辑设置过期时间太短,或者前端没有正确地把 token 放进请求头。排查思路是先看后端日志里有没有对应的鉴权报错,再看浏览器 Network 面板里请求头带没带 Authorization 字段。
5.3 常见问题速查表
| 问题现象 | 常见原因 | 排查思路 |
|---|---|---|
| 页面打不开 | 前端端口被占或启动失败 | 查看 Node 控制台报错,换一个 dev 端口 |
| 接口返回 404 | 代理配置没匹配到 API 路径 | 检查前端 baseURL 和后端控制器映射路径 |
| 接口返回 500 | 数据库连接失败或 SQL 异常 | 看后端日志堆栈,确认数据库连接串 |
| 登录后马上失效 | token 过期时间太短 | 调整 token 有效期或检查前端拦截器 |
| 人脸录入失败 | 摄像头未授权或后端服务未部署 | 分前端采集、后端检测两段验证 |
| 刷脸登录识别错人 | 相似度阈值过低 | 调高阈值并重新测试样本 |
| 中文乱码 | 连接串没指定 utf8mb4 | 修改连接串并转换表字符集 |
| 号源显示负数 | 并发下单时没有锁保护 | 在 SQL 更新中加条件判断 |
| 取消后号源没回补 | 取消逻辑缺少排班表更新 | 补上已约号量减一的逻辑 |
5.4 一套通用的排查流程
遇到问题不要直接改代码,我的习惯是“从外往里、分层确认”。第一层确认环境:数据库连不连得上、服务启动没启动、端口通不通。第二层确认接口:用 Postman 或 curl 直接调用后端接口,看返回体和 HTTP 状态码,跳过前端只看后端是否正常。第三层确认前端:看浏览器 Network 面板里实际发的请求地址、请求头、响应数据,基本就能定位到问题出在前端、代理还是后端。
定位清楚以后再动手,避免陷入“改一行测一次”的恶性循环。对于我来说,90% 的项目启动问题都能通过这三步在半小时内解决。
6. 源码阅读、文档利用与二次开发建议
6.1 拿到源码先看什么
很多人拿到源码包的第一反应是直接运行,运行失败就开始烦躁。我更建议先花半小时做“摸底”,按这个顺序看:根目录结构、数据库脚本、配置文件、后端入口、前端路由。
根目录结构能告诉你代码分几块,常见布局是 backend 与 frontend 两大部分,看目录名就能判断。数据库脚本里藏着整个系统的数据模型,看完表结构就能大概知道业务有哪些模块。配置文件里是环境依赖信息,比如端口、数据库地址、第三方接口地址,所有需要自定义改动的信息都在这一层。后端入口一般是启动类或者 app 主模块,从这里可以看出项目用了什么框架、有哪些过滤器拦截器。前端路由则告诉你页面之间的跳转关系,能快速把功能点和界面映射起来。
读源码不要逐行读,而是跟业务主线读:注册登录流程怎么写、人脸特征怎么存、提交预约时执行了什么 SQL。主线读通之后,其他模块都是相似套路,一通百通。
6.2 配套设计文档(lw)如何高效利用
这套项目里带的配套设计文档,也就是俗称的 lw,很多人只看作应付格式的材料,其实它是快速理解系统的捷径。设计文档通常包含项目背景、需求分析、系统设计、数据库设计、接口设计、核心代码说明和测试结果,这些章节和项目模块有对应关系。
我的建议是先看文档中的“系统功能模块图”和“数据库 ER 图”,把这两个图理解透,再看代码会觉得清晰很多。文档里的“核心算法”章节如果写了人脸识别的流程,那基本就是人脸模块代码的文字版,对照着看效率翻倍。如果是用来做论文或者答辩,这份文档还是最直接的素材来源,只需要把其中的项目背景、技术选型理由、测试数据按照自己的真实运行结果更新一遍,工作量会小很多。
这里要提醒一句:拿现成文档的时候,务必把测试数据改成自己实际跑出来的数据。很多同学把文档里的“测试结果”原封不动交上去,结果自己的环境跑出来的数字和文档对不上,答辩时被一问就露馅。老老实实重新跑一遍测试,用真实数据更新文档,这是最基本的诚信问题。
6.3 值得投入的扩展方向
一套基础预约挂号系统跑通之后,如果想让它更有竞争力,我建议优先考虑这几个扩展方向。
小程序端是性价比最高的扩展。医院场景里患者普遍不愿意额外下载 App,小程序扫码即用,体验契合实际使用习惯。技术上可以在现有后端接口的基础上,单独写一个小程序前端,复用现有的预约、排班、人脸绑定逻辑。
对接支付是另一个高频需求。现在系统里如果只有线下支付,就缺少一个真实的交易闭环。对接微信支付或支付宝需要商户资质,演示环境可以用模拟支付来走通回调流程,重点把支付状态机和订单状态机的转换逻辑补齐。
排队叫号和在线问诊也值得做。排队叫号相当于在现有预约链路上增加一个队列状态,在线问诊则是在预约后增加一种轻量服务,资料和信息都是现成的,扩展起来复杂度可控。
6.4 答辩与讲解时的准备思路
如果是拿着这个项目去答辩或者演示,重点准备的内容其实集中在几个方向:为什么选人脸识别、人脸识别怎么做的、并发情况下怎么保证不超卖、数据表为什么这么设计。
讲人脸识别时,最忌讳只说“用了某库所以能识别”。正确的思路是讲检测、对齐、特征提取、特征比对四个步骤,每一步用了什么方法,为什么选这个方法。哪怕代码是封装好的库,也要知道底层大致是什么原理。讲数据库设计时,最好拿一张预约表出来,说明字段的用途和状态字段的流转过程。讲并发控制时,把乐观锁方案说清楚,基本就是加分项。
我特意强调过很多次“主流程闭环优先”,在演示时也是这样。宁可只演示注册、刷脸登录、预约挂号、医生核验这条主链路,也别花五分钟去演示管理后台添加科室这种边角功能。面试官或者评委会先观察你对整体业务的理解,细节功能只能锦上添花,不能雪中送炭。
最后再说点个人体会。我接手过很多套类似的完整项目包,发现一个共同规律:凡是能顺利跑通并讲清楚的人,都不是代码写得有多好,而是把业务链路吃透了。人脸识别听起来高大上,但在这套系统里它只是身份核验的一个手段,真正的核心是预约挂号的业务逻辑,是订单状态的流转、号源的管理、角色的权限划分。先把这个主干吃透,再考虑人脸识别怎么接入,你会发现整个系统变得特别好理解。
还有一个小技巧分享给大家:拿到任何一套新源码,第一件事永远是先复制一份留作备份,然后才在原目录里改。配置改乱了、代码误删了、依赖装崩了,随时可以从备份恢复,这一条能帮你省掉大量从头再来的痛苦。后续如果你们在做类似项目时遇到具体报错,欢迎把关键日志发出来一起看看,这类系统的基本盘就是那些,把业务链路理清楚,很多问题你会有一种水到渠成的解决感。