7.7 KiB
7.7 KiB
挂号预约排班状态过滤修复
问题描述
在挂号预约时,系统显示了所有时间段(9:00-18:00),但没有检查医生的排班状态。即使医生休息或停诊,系统仍然显示可预约时段。
问题截图说明
从截图可以看到:
- 周三 03-04 下午显示"休息"
- 但系统仍然可能显示下午的预约时段
排班状态定义
根据数据库模型 Roster,排班状态定义如下:
| 状态值 | 状态名称 | 说明 |
|---|---|---|
| 1 | 出诊 | 医生正常出诊,可以预约 |
| 2 | 停诊 | 医生停诊,不可预约 |
| 3 | 休息 | 医生休息,不可预约 |
| 4 | 请假 | 医生请假,不可预约 |
排班时段定义
| 时段值 | 时段名称 | 时间范围 |
|---|---|---|
| 1 | 上午 | 09:00-12:00 |
| 2 | 下午 | 14:00-18:00 |
问题根源
原来的逻辑
public static function getAvailableSlots(array $params)
{
// 1. 直接生成 9:00-18:00 的所有时间段
for ($hour = 9; $hour < 18; $hour++) {
for ($minute = 0; $minute < 60; $minute += 15) {
$slots[] = [
'time' => sprintf('%02d:%02d', $hour, $minute),
'available' => true,
'quota' => 1
];
}
}
// 2. 只检查已预约的时间段
// ❌ 没有检查医生的排班状态
}
问题
- 不检查医生是否有排班
- 不检查排班状态(出诊/休息/停诊)
- 不区分上午/下午时段
- 即使医生休息也显示可预约
解决方案
修复后的逻辑
public static function getAvailableSlots(array $params)
{
// 1. 先检查医生在该日期是否有出诊排班
$rosters = Roster::where([
'doctor_id' => $doctorId,
'date' => $date,
'status' => 1 // ✅ 只查询出诊状态
])->select()->toArray();
// 如果没有出诊排班,返回空数组
if (empty($rosters)) {
return ['slots' => []];
}
// 2. 根据排班时段生成时间段
foreach ($rosters as $roster) {
if ($roster['period'] == 1) {
// 上午:9:00-12:00
$startHour = 9;
$endHour = 12;
} elseif ($roster['period'] == 2) {
// 下午:14:00-18:00
$startHour = 14;
$endHour = 18;
}
// 生成15分钟间隔的时间段
for ($hour = $startHour; $hour < $endHour; $hour++) {
for ($minute = 0; $minute < 60; $minute += 15) {
$slots[] = [
'time' => sprintf('%02d:%02d', $hour, $minute),
'available' => true,
'quota' => 1,
'period' => $roster['period']
];
}
}
}
// 3. 查询已预约的时间段并标记
// ...
}
修复效果
场景 1:医生上午出诊,下午休息
排班数据:
date: 2026-03-04
period: 1 (上午)
status: 1 (出诊)
预约时段:
- ✅ 显示:09:00, 09:15, 09:30, ..., 11:45
- ❌ 不显示:14:00-18:00 的时段
场景 2:医生全天休息
排班数据:
date: 2026-03-04
period: 1 (上午)
status: 3 (休息)
date: 2026-03-04
period: 2 (下午)
status: 3 (休息)
预约时段:
- ❌ 不显示任何时段
- 💡 提示:该医生暂无可预约时段
场景 3:医生全天出诊
排班数据:
date: 2026-03-04
period: 1 (上午)
status: 1 (出诊)
date: 2026-03-04
period: 2 (下午)
status: 1 (出诊)
预约时段:
- ✅ 显示:09:00-11:45 (上午)
- ✅ 显示:14:00-17:45 (下午)
场景 4:医生上午停诊,下午出诊
排班数据:
date: 2026-03-04
period: 1 (上午)
status: 2 (停诊)
date: 2026-03-04
period: 2 (下午)
status: 1 (出诊)
预约时段:
- ❌ 不显示:09:00-12:00 的时段
- ✅ 显示:14:00-17:45 (下午)
时间段生成规则
上午时段(period = 1)
开始时间:09:00
结束时间:12:00
间隔:15分钟
生成时段:
09:00, 09:15, 09:30, 09:45,
10:00, 10:15, 10:30, 10:45,
11:00, 11:15, 11:30, 11:45
下午时段(period = 2)
开始时间:14:00
结束时间:18:00
间隔:15分钟
生成时段:
14:00, 14:15, 14:30, 14:45,
15:00, 15:15, 15:30, 15:45,
16:00, 16:15, 16:30, 16:45,
17:00, 17:15, 17:30, 17:45
前端显示逻辑
前端已经正确处理了排班状态的过滤:
// 加载医生排班信息
const loadDoctorRoster = async () => {
const res = await rosterLists({
doctor_id: selectedDoctorId.value,
start_date: startDate,
end_date: endDate,
status: 1 // ✅ 只查询出诊状态
})
// 提取有排班的日期
if (res?.lists && res.lists.length > 0) {
doctorRosterDates.value = [...new Set(res.lists.map(item => item.date))].sort()
}
}
完整流程
1. 选择医生
用户选择医生 → 加载医生排班 → 只显示有出诊排班的日期
2. 选择日期
用户选择日期 → 加载该日期的可用时段 → 只显示出诊时段的时间
3. 选择时段
用户选择时段 → 检查是否已被预约 → 创建预约
数据库查询
查询医生出诊排班
SELECT * FROM zyt_doctor_roster
WHERE doctor_id = 1
AND date = '2026-03-04'
AND status = 1 -- 只查询出诊状态
ORDER BY period ASC;
查询已预约时段
SELECT appointment_time FROM zyt_doctor_appointment
WHERE doctor_id = 1
AND appointment_date = '2026-03-04'
AND status = 1 -- 只查询有效预约
测试用例
测试 1:医生全天出诊
-- 插入排班
INSERT INTO zyt_doctor_roster (doctor_id, date, period, status, quota, max_patients)
VALUES
(1, '2026-03-10', 1, 1, 20, 20), -- 上午出诊
(1, '2026-03-10', 2, 1, 20, 20); -- 下午出诊
预期结果:
- 显示上午时段:09:00-11:45
- 显示下午时段:14:00-17:45
测试 2:医生上午出诊,下午休息
INSERT INTO zyt_doctor_roster (doctor_id, date, period, status, quota, max_patients)
VALUES
(1, '2026-03-11', 1, 1, 20, 20), -- 上午出诊
(1, '2026-03-11', 2, 3, 0, 0); -- 下午休息
预期结果:
- 显示上午时段:09:00-11:45
- 不显示下午时段
测试 3:医生全天休息
INSERT INTO zyt_doctor_roster (doctor_id, date, period, status, quota, max_patients)
VALUES
(1, '2026-03-12', 1, 3, 0, 0), -- 上午休息
(1, '2026-03-12', 2, 3, 0, 0); -- 下午休息
预期结果:
- 该日期不出现在可选日期列表中
- 如果强制访问,不显示任何时段
测试 4:医生上午停诊,下午出诊
INSERT INTO zyt_doctor_roster (doctor_id, date, period, status, quota, max_patients)
VALUES
(1, '2026-03-13', 1, 2, 0, 0), -- 上午停诊
(1, '2026-03-13', 2, 1, 20, 20); -- 下午出诊
预期结果:
- 不显示上午时段
- 显示下午时段:14:00-17:45
已修改的文件
- ✅
server/app/adminapi/logic/doctor/AppointmentLogic.php
优势
- 准确性:只显示医生实际出诊的时段
- 用户体验:避免用户选择无效时段
- 数据一致性:预约数据与排班数据保持一致
- 灵活性:支持上午/下午独立设置状态
- 可维护性:逻辑清晰,易于理解和维护
注意事项
- 排班状态:只有
status = 1(出诊)的排班才会生成时段 - 时段区分:上午和下午时段独立判断
- 时间格式:统一使用
HH:MM格式(如:09:00) - 已预约检查:在生成时段后,还需要检查已预约情况
- 空数组处理:如果没有出诊排班,返回空数组而不是错误
修复日期: 2024-03-04 状态: ✅ 完成 影响范围: 挂号预约功能