You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot MVC REST API医生可预约时段展示方案咨询

嘿,针对你这个诊所预约系统的医生可预约时段展示需求,我来分享一套经过实践验证的最优方案,从数据库设计到Spring Boot实现再到细节优化都给你梳理清楚:

核心方案设计

1. 数据库表结构设计

首先得搭好基础数据模型,确保数据关联清晰:

  • 诊所表(clinics):存储诊所基础信息,字段示例:id(主键), name, address
  • 医生表(doctors):关联所属诊所,字段示例:id(主键), name, clinic_id(外键关联clinics.id), specialty
  • 预约表(appointments):记录已预约信息,字段示例:id(主键), doctor_id(外键关联doctors.id), patient_id, appointment_date(日期类型), start_time(时间类型), end_time(时间类型,自动计算为start_time+30分钟), status

2. 核心业务逻辑实现

核心思路是生成当日全量基础时段 → 排除已预约时段 → 返回可用时段:

  1. 生成基础时段:从早7点到晚6点,每30分钟一个时段(即7:00、7:30...17:30,因为17:30+30分钟刚好到18:00结束)
  2. 过滤已占用时段:查询该医生当日所有已预约的start_time,从基础时段中移除这些时间点
  3. 参数校验:确保医生属于所选诊所、查询日期不为过去日期

3. Spring Boot REST API 实现

代码示例

Service层核心逻辑

@Service
public class AppointmentService {

    @Autowired
    private AppointmentRepository appointmentRepository;

    @Autowired
    private DoctorRepository doctorRepository;

    public List<SlotDTO> getAvailableSlots(Long clinicId, Long doctorId, LocalDate date) {
        // 校验医生归属诊所
        Doctor doctor = doctorRepository.findById(doctorId)
                .orElseThrow(() -> new IllegalArgumentException("指定医生不存在"));
        if (!doctor.getClinicId().equals(clinicId)) {
            throw new IllegalArgumentException("该医生不属于所选诊所");
        }

        // 生成当日全量基础时段
        List<LocalTime> allBaseSlots = new ArrayList<>();
        LocalTime currentTime = LocalTime.of(7, 0);
        LocalTime dailyEndTime = LocalTime.of(18, 0);
        while (currentTime.isBefore(dailyEndTime)) {
            allBaseSlots.add(currentTime);
            currentTime = currentTime.plusMinutes(30);
        }

        // 查询已预约时段
        List<LocalTime> bookedSlots = appointmentRepository.findBookedStartTimes(doctorId, date);

        // 过滤可用时段并转换为DTO
        return allBaseSlots.stream()
                .filter(slot -> !bookedSlots.contains(slot))
                .map(slot -> new SlotDTO(slot, slot.plusMinutes(30)))
                .collect(Collectors.toList());
    }
}

// 时段DTO定义
public class SlotDTO {
    private LocalTime startTime;
    private LocalTime endTime;

    // 构造器、Getter、Setter省略
}

Repository层查询方法

@Repository
public interface AppointmentRepository extends JpaRepository<Appointment, Long> {
    @Query("SELECT a.startTime FROM Appointment a WHERE a.doctorId = :doctorId AND a.appointmentDate = :date")
    List<LocalTime> findBookedStartTimes(@Param("doctorId") Long doctorId, @Param("date") LocalDate date);
}

Controller层API接口

@RestController
@RequestMapping("/api/clinics")
public class AppointmentController {

    @Autowired
    private AppointmentService appointmentService;

    @GetMapping("/{clinicId}/doctors/{doctorId}/available-slots")
    public ResponseEntity<List<SlotDTO>> getAvailableSlots(
            @PathVariable Long clinicId,
            @PathVariable Long doctorId,
            @RequestParam("date") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {
        // 校验日期合法性
        if (date.isBefore(LocalDate.now())) {
            return ResponseEntity.badRequest().body(Collections.emptyList());
        }

        try {
            List<SlotDTO> availableSlots = appointmentService.getAvailableSlots(clinicId, doctorId, date);
            return ResponseEntity.ok(availableSlots);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(Collections.emptyList());
        }
    }
}

4. 前端交互建议

  • 联动选择:用户选完诊所后,异步加载该诊所的医生列表;选完医生后,弹出日历组件选择日期
  • 时段渲染:将API返回的可用时段渲染为可点击按钮,若需展示已预约时段可置灰禁用
  • 实时性:预约成功后,立即刷新当前日期的可用时段列表

5. 优化与边界处理

  • 缓存优化:用Redis缓存热门医生的可用时段,缓存Key设为available_slots:{clinicId}:{doctorId}:{date},有效期1小时,有新预约时删除对应缓存
  • 医生休息处理:若需支持医生固定休息日/时段,可新增doctor_rest_days表,在生成基础时段前先校验日期是否为休息日
  • 并发防护:预约时需加乐观锁或数据库行锁,防止同一时段被多个用户同时预约

内容的提问来源于stack exchange,提问作者Code reviewer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:47:49