1. 项目背景与需求分析
社区诊所作为基层医疗服务的重要载体,每天面临着大量患者的就诊需求。传统的人工挂号排队方式存在诸多痛点:患者需要早早到现场排队取号,候诊时间长;诊所难以合理分配医生资源;高峰期容易造成人员聚集,既影响就诊效率又增加管理压力。
这套基于ThinkPHP开发的诊所在线挂号与排队系统,正是为了解决这些实际问题而设计的。我在开发过程中走访了多家社区诊所,发现以下几个核心需求:
- 患者端需求:
- 能够提前预约挂号,减少现场等待时间
- 实时查看排队进度,避免长时间滞留诊所
- 接收就诊提醒通知,合理安排个人时间
- 医生端需求:
- 清晰掌握当日就诊患者情况
- 快速标记就诊状态,提高接诊效率
- 便捷生成电子病历,减少文书工作
- 管理端需求:
- 可视化数据统计,辅助排班决策
- 合理分配医疗资源,提高运营效率
- 减少人工调度成本,降低管理难度
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计
2.1 技术选型考量
选择ThinkPHP 6.0作为后端框架主要基于以下考虑:
- 成熟的MVC架构,便于团队协作开发
- 完善的文档和活跃的社区支持
- 内置丰富的安全防护机制
- 良好的性能表现,适合中小型应用
前端采用Vue.js+Element UI组合,主要优势在于:
- 组件化开发,提高代码复用率
- 响应式设计,完美适配多端设备
- 丰富的UI组件库,加速开发进程
数据库选用MySQL+Redis组合:
- MySQL负责核心数据持久化存储
- Redis处理高并发场景下的队列状态更新
- 两者结合既保证数据安全又提升系统响应速度
2.2 系统架构图
code复制[患者终端] ←HTTP/HTTPS→ [Web服务器] ←→ [应用服务器]
↑
↓
[医生工作站] ←WebSocket→ [消息队列] ←→ [数据库集群]
↑
↓
[管理后台] ←HTTP/HTTPS→ [缓存服务器]
这种分层架构设计使得系统各模块解耦,便于后期扩展和维护。特别是引入WebSocket协议实现实时排队状态推送,避免了传统轮询方式带来的服务器压力。
3. 核心功能实现
3.1 在线挂号模块
挂号流程的关键代码实现:
php复制// 挂号控制器
class RegisterController extends Controller
{
// 获取可预约时间段
public function getTimeSlots()
{
$doctorId = input('doctor_id');
$date = input('date');
// 检查医生排班情况
$schedule = ScheduleModel::where([
'doctor_id' => $doctorId,
'work_date' => $date,
'status' => 1
])->find();
if(!$schedule) {
return json(['code' => 400, 'msg' => '该医生当日无排班']);
}
// 计算剩余可预约数
$booked = RegistrationModel::where([
'doctor_id' => $doctorId,
'visit_date' => $date,
'status' => ['in', [1,2]]
])->count();
$available = $schedule['max_patients'] - $booked;
// 返回时间段信息
return json([
'code' => 200,
'data' => [
'start_time' => $schedule['start_time'],
'end_time' => $schedule['end_time'],
'interval' => $schedule['time_interval'],
'available' => $available > 0 ? $available : 0
]
]);
}
// 提交预约
public function submit()
{
$data = input('post.');
// 验证患者信息
$validate = new RegisterValidate();
if(!$validate->check($data)){
return json(['code' => 400, 'msg' => $validate->getError()]);
}
// 检查时间段是否可用
$conflict = RegistrationModel::where([
'doctor_id' => $data['doctor_id'],
'visit_date' => $data['visit_date'],
'time_slot' => $data['time_slot'],
'status' => ['in', [1,2]]
])->count();
if($conflict > 0){
