1. 项目背景与需求分析
医院挂号预约管理系统是医疗信息化建设中的核心组成部分。随着门诊量的持续增长,传统窗口挂号模式已无法满足患者需求,线上预约挂号成为缓解"看病难"问题的有效手段。我们基于ThinkPHP和Laravel双框架开发的这套系统,旨在为中小型医疗机构提供高性价比的解决方案。
从实际运营数据来看,上线预约系统后:
- 患者平均候诊时间缩短40%
- 挂号窗口排队人数减少65%
- 爽约率从15%降至7%以下
- 医生接诊效率提升30%
系统需要解决的核心痛点包括:
- 号源分配不合理导致的"秒杀"现象
- 黄牛利用技术手段抢号
- 特殊人群(如老年人)的操作障碍
- 多终端(PC/微信/小程序)的数据同步
- 突发情况下的号源动态调整
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计
2.1 框架选型考量
采用ThinkPHP+Laravel混合架构主要基于以下考量:
ThinkPHP优势:
- 国产框架更符合医疗行业安全要求
- 内置RBAC权限控制模块
- 文档完善且社区支持度高
- 对微信生态集成友好
Laravel优势:
- Eloquent ORM提供更优雅的数据操作
- 队列系统适合处理预约短信通知
- 测试工具链完善保障系统稳定性
- Blade模板引擎更利于前后端分离
实际部署中:
- 用户认证、支付等核心模块用ThinkPHP开发
- 后台管理、数据分析采用Laravel实现
- 通过JWT实现跨框架会话保持
2.2 数据库设计要点
MySQL表结构设计遵循医疗行业规范:
sql复制CREATE TABLE `schedule` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`doctor_id` int(11) NOT NULL COMMENT '医生ID',
`department_id` int(11) NOT NULL COMMENT '科室ID',
`date` date NOT NULL COMMENT '出诊日期',
`time_slot` varchar(20) NOT NULL COMMENT '时段(morning/afternoon/night)',
`total` smallint(6) NOT NULL DEFAULT '0' COMMENT '总号源',
`remain` smallint(6) NOT NULL DEFAULT '0' COMMENT '剩余号源',
`status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1开放 0停诊',
PRIMARY KEY (`id`),
UNIQUE KEY `udx_doctor_time` (`doctor_id`,`date`,`time_slot`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='排班表';
关键设计原则:
- 建立医生-日期-时段的唯一约束防止重复排班
- 使用utf8mb4字符集支持emoji等特殊字符
- 预留status字段应对临时停诊情况
- 将时段枚举值固化减少存储空间
3. 核心功能实现
3.1 预约业务流程
典型预约流程时序:
- 患者选择科室/医生
- 系统返回可预约时段(15分钟粒度)
- 选择时段后锁定号源(Redis分布式锁)
- 10分钟内完成支付
- 短信通知+生成电子凭证
防黄牛技术方案:
php复制// 预约频率限制中间件
class AppointmentRateLimit
{
public function handle($request, Closure $next)
{
$key = 'rate_limit:'.$request->ip();
if (Redis::get($key) > 3) {
abort(429, '操作过于频繁');
}
Redis::incr($key);
Redis::expire($key, 3600);
return $next($request);
}
}
3.2 智能排班算法
排班逻辑需考虑:
- 医生职称(主任/副主任医师号源比例)
- 历史接诊量(热门医生增加号源)
- 特殊时段(周末/节假日调整)
- 急诊联动(预留应急号源)
实现示例:
php复制public function generateSchedule(Doctor $doctor, $date)
{
$base = 20; // 基础号源
$adjustment = 0;
// 职称系数
if ($doctor->title == '主任医师') {
$adjustment += 5;
}
// 历史接诊量系数
$avg = Appointment::where('doctor_id', $doctor->id)
->whereBetween('created_at', [now()->subMonth(), now()])
->avg('per_hour');
$adjustment += min(5, floor($avg / 10));
// 特殊日期处理
if (Holiday::isHoliday($date)) {
$adjustment -= 3;
}
return max(5, $base + $adjustment); // 最少保留5个号源
}
4. 特殊场景处理
4.1 退号即时释放
退号处理流程:
- 患者发起退号请求
- 系统校验是否超时(就诊前2小时可退)
- 原号源状态改为"可预约"
- 加入待释放队列(防止瞬时并发)
- 定时任务每分钟处理队列
关键代码:
php复制// 使用Laravel队列处理退号
class ReleaseNumberJob implements ShouldQueue
{
public function handle()
{
$numbers = ReleaseQueue::where('status', 0)
->limit(50)
->get();
DB::transaction(function () use ($numbers) {
foreach ($numbers as $item) {
Schedule::where('id', $item->schedule_id)
->increment('remain');
$item->update(['status' => 1]);
}
});
}
}
4.2 停诊自动通知
停诊处理方案:
- 管理员标记排班为停诊状态
- 系统扫描该排班所有预约记录
- 通过短信+站内信双重通知
- 提供改约快捷入口
- 记录操作日志备查
通知模板示例:
code复制【XX医院】尊敬的{name}:您预约的{doctor}医生{date}{time}的号源因故取消,请登录小程序重新预约或致电{phone}咨询。给您带来不便敬请谅解。
5. 安全与性能优化
5.1 安全防护措施
医疗系统特别需要注意:
- 等保三级合规要求
- 患者隐私数据加密
- 防SQL注入处理
- 敏感操作日志审计
ThinkPHP安全配置示例:
php复制// config.php
return [
'default_filter' => 'htmlspecialchars,strip_tags',
'csrf_token_on' => true,
'csrf_token_name' => '__hash__',
'csrf_token_reset' => true
];
// 模型层自动加密
class Patient extends Model
{
protected function getMobileAttr($value)
{
return substr_replace($value, '****', 3, 4);
}
}
5.2 高并发优化方案
预约高峰期的技术应对:
- 使用Redis集群分担MySQL压力
- 热门科室号源采用分段放号
- 前端增加验证码二次确认
- Nginx限流配置
性能对比测试数据:
| 方案 | 100并发 | 500并发 | 响应时间 |
|---|---|---|---|
| 纯MySQL | 78%成功率 | 31%成功率 | 2.3s |
| Redis+MySQL | 100%成功率 | 98%成功率 | 0.4s |
Nginx限流配置示例:
nginx复制limit_req_zone $binary_remote_addr zone=appointment:10m rate=5r/s;
location /api/appointment {
limit_req zone=appointment burst=10 nodelay;
proxy_pass http://php_backend;
}
6. 部署与监控
6.1 容器化部署
使用Docker-compose部署方案:
yaml复制version: '3'
services:
app:
image: php:7.4-fpm
volumes:
- ./tp:/var/www/tp
- ./laravel:/var/www/laravel
networks:
- app-net
nginx:
image: nginx:1.19
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
redis:
image: redis:6
ports:
- "6379:6379"
command: redis-server --requirepass ${REDIS_PASS}
6.2 监控指标设置
必备监控项包括:
- 预约成功率(>99.5%)
- 支付超时率(<1%)
- 接口响应时间(P95<500ms)
- 服务器CPU/Memory使用率
- MySQL慢查询数量
Prometheus监控配置示例:
yaml复制- job_name: 'php_fpm'
metrics_path: '/fpm_status'
static_configs:
- targets: ['app:9000']
labels:
env: 'production'
- job_name: 'mysql'
static_configs:
- targets: ['mysql:9104']
这套系统在实际部署中需要特别注意医生排班习惯的差异,我们遇到过某位老专家坚持要手动控制每个时段的号源数量,为此特别开发了"号源微调"功能。另一个经验是提前与财务部门确认对账需求,我们最初版本就因为缺少明细导出功能导致月底对账困难。
