前言
💖💖作者:计算机程序员小杨 💙💙个人简介:我是一名计算机相关专业的从业者,擅长Java、微信小程序、Python、Golang、安卓Android等多个IT方向。会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。热爱技术,喜欢钻研新工具和框架,也乐于通过代码解决实际问题,大家有技术代码这一块的问题可以问我! 💛💛想说的话:感谢大家的关注与支持! 💕💕文末获取源码联系 计算机程序员小杨 💜💜 网站实战项目 安卓/小程序实战项目 大数据实战项目 深度学习实战项目 计算机毕业设计选题 💜💜
一.开发工具简介
开发语言:Java+Python(两个版本都支持) 后端框架:Spring Boot(Spring+SpringMVC+Mybatis)+Django(两个版本都支持) 前端:Vue+ElementUI+HTML 数据库:MySQL 系统架构:B/S 开发工具:IDEA(Java的)或者PyCharm(Python的)
二.系统内容简介
本系统是一个基于Spring Boot和Vue技术架构开发的智慧医疗预约挂号平台,采用B/S模式实现医患双方的便捷对接与医疗服务流程的数字化管理。系统运用MySQL数据库进行数据存储,通过前后端分离的开发方式,为患者用户和医院管理方提供全方位的就医服务支持。平台核心功能涵盖用户账号的注册与管理、医生信息的录入与维护、医生排班的灵活调度与可视化展示、科室分类的层级化组织、门诊挂号的在线预约与号源管理、诊断报告的电子化归档与查询、取消预约的退号处理与号源释放、药品信息的数据库建立与检索、处方开药的医嘱记录与药品关联、轮播图的首页展示与信息推送以及个人中心的就诊历史和健康档案管理。系统通过整合这些业务模块,构建起一个流程清晰、操作便捷、信息透明的医疗服务体系,有效缓解了传统挂号模式下排队时间长、号源信息不透明、就医流程繁琐等突出问题,为医疗机构的信息化建设和患者的就医体验改善提供了实用的技术平台,推动医疗服务向智能化、人性化方向发展。
三.系统功能演示
四.系统界面展示
五.系统源码展示
/**
* 核心功能一: 门诊挂号预约与号源智能分配管理
* 处理挂号预约、号源查询、预约时段分配、冲突检测等核心业务
*/
@PostMapping("/createAppointment")
@Transactional(rollbackFor = Exception.class)
public Result createAppointment(@RequestBody Appointment appointment, HttpServletRequest request) {
String token = request.getHeader("Authorization");
Long userId = JwtUtil.getUserId(token);
// 验证用户实名认证状态
User user = userMapper.selectById(userId);
if (user == null || user.getAuthStatus() != 1) {
return Result.error("请先完成实名认证后再进行挂号预约");
}
// 查询医生排班信息
DoctorSchedule schedule = doctorScheduleMapper.selectById(appointment.getScheduleId());
if (schedule == null || schedule.getStatus() != 1) {
return Result.error("该排班不存在或已停诊");
}
// 检查预约日期是否有效
Date appointmentDate = appointment.getAppointmentDate();
Date today = DateUtil.getToday();
if (appointmentDate.before(today)) {
return Result.error("不能预约过去的日期");
}
long dayDiff = DateUtil.getDaysBetween(today, appointmentDate);
if (dayDiff > 7) {
return Result.error("预约时间不能超过7天");
}
// 检查号源是否充足
QueryWrapper<Appointment> countWrapper = new QueryWrapper<>();
countWrapper.eq("schedule_id", appointment.getScheduleId())
.eq("appointment_date", appointmentDate)
.in("status", Arrays.asList(0, 1)); // 待就诊和就诊中
int bookedCount = appointmentMapper.selectCount(countWrapper);
if (bookedCount >= schedule.getMaxPatients()) {
return Result.error("当前时段号源已满,请选择其他时段");
}
// 检查用户是否有重复预约
QueryWrapper<Appointment> duplicateWrapper = new QueryWrapper<>();
duplicateWrapper.eq("user_id", userId)
.eq("doctor_id", schedule.getDoctorId())
.eq("appointment_date", appointmentDate)
.in("status", Arrays.asList(0, 1));
if (appointmentMapper.selectCount(duplicateWrapper) > 0) {
return Result.error("您已预约该医生当天的号源,请勿重复预约");
}
// 检查用户当天预约总数限制
QueryWrapper<Appointment> dailyLimitWrapper = new QueryWrapper<>();
dailyLimitWrapper.eq("user_id", userId)
.eq("appointment_date", appointmentDate)
.in("status", Arrays.asList(0, 1));
if (appointmentMapper.selectCount(dailyLimitWrapper) >= 3) {
return Result.error("您当天的预约已达上限(3个),无法继续预约");
}
// 分配挂号序号
int queueNumber = bookedCount + 1;
// 创建挂号预约记录
appointment.setUserId(userId);
appointment.setDoctorId(schedule.getDoctorId());
appointment.setDepartmentId(schedule.getDepartmentId());
appointment.setQueueNumber(queueNumber);
appointment.setRegistrationFee(schedule.getRegistrationFee());
appointment.setStatus(0); // 待就诊
appointment.setCreateTime(new Date());
// 生成预约编号
String appointmentNo = "AP" + DateUtil.format(new Date(), "yyyyMMddHHmmss") + userId;
appointment.setAppointmentNo(appointmentNo);
appointmentMapper.insert(appointment);
// 更新排班已预约数量
schedule.setBookedCount(schedule.getBookedCount() + 1);
doctorScheduleMapper.updateById(schedule);
// 发送预约成功通知
sendNotification(userId, "预约成功,就诊序号:" + queueNumber + ",请提前15分钟到达诊室");
// 记录用户就诊历史
MedicalHistory history = new MedicalHistory();
history.setUserId(userId);
history.setAppointmentId(appointment.getId());
history.setDoctorId(schedule.getDoctorId());
history.setDepartmentId(schedule.getDepartmentId());
history.setVisitDate(appointmentDate);
history.setStatus(0); // 未就诊
medicalHistoryMapper.insert(history);
Map<String, Object> resultData = new HashMap<>();
resultData.put("appointmentNo", appointmentNo);
resultData.put("queueNumber", queueNumber);
resultData.put("doctorName", schedule.getDoctorName());
resultData.put("appointmentDate", appointmentDate);
return Result.success("挂号预约成功", resultData);
}
/**
* 核心功能二: 取消预约与号源动态释放管理
* 处理预约取消申请、退费计算、号源释放、序号重排等业务
*/
@PostMapping("/cancelAppointment")
@Transactional(rollbackFor = Exception.class)
public Result cancelAppointment(@RequestParam Long appointmentId, @RequestParam String reason,
HttpServletRequest request) {
String token = request.getHeader("Authorization");
Long userId = JwtUtil.getUserId(token);
// 查询预约记录
Appointment appointment = appointmentMapper.selectById(appointmentId);
if (appointment == null || !appointment.getUserId().equals(userId)) {
return Result.error("预约记录不存在或无权限操作");
}
// 验证预约状态
if (appointment.getStatus() == 2) {
return Result.error("该预约已完成就诊,无法取消");
}
if (appointment.getStatus() == 3) {
return Result.error("该预约已取消,请勿重复操作");
}
// 计算取消时间与预约时间的间隔
Date appointmentDate = appointment.getAppointmentDate();
Date now = new Date();
long hoursDiff = DateUtil.getHoursBetween(now, appointmentDate);
// 根据取消时间计算退费比例
BigDecimal refundRate;
String refundDesc;
if (hoursDiff >= 24) {
refundRate = BigDecimal.valueOf(1.0); // 提前24小时以上全额退款
refundDesc = "全额退款";
} else if (hoursDiff >= 2) {
refundRate = BigDecimal.valueOf(0.5); // 提前2-24小时退50%
refundDesc = "退款50%";
} else if (hoursDiff > 0) {
refundRate = BigDecimal.ZERO; // 2小时内不退款
refundDesc = "不予退款";
} else {
return Result.error("预约时间已过,无法取消");
}
BigDecimal refundAmount = appointment.getRegistrationFee()
.multiply(refundRate)
.setScale(2, RoundingMode.HALF_UP);
// 创建取消预约记录
CancelAppointment cancelRecord = new CancelAppointment();
cancelRecord.setAppointmentId(appointmentId);
cancelRecord.setUserId(userId);
cancelRecord.setDoctorId(appointment.getDoctorId());
cancelRecord.setCancelReason(reason);
cancelRecord.setOriginalFee(appointment.getRegistrationFee());
cancelRecord.setRefundAmount(refundAmount);
cancelRecord.setRefundRate(refundRate);
cancelRecord.setCancelTime(now);
cancelRecord.setStatus(0); // 待退款
cancelAppointmentMapper.insert(cancelRecord);
// 更新预约状态
appointment.setStatus(3); // 已取消
appointment.setCancelTime(now);
appointmentMapper.updateById(appointment);
// 获取当前排班信息
DoctorSchedule schedule = doctorScheduleMapper.selectById(appointment.getScheduleId());
// 释放号源并更新已预约数量
schedule.setBookedCount(schedule.getBookedCount() - 1);
doctorScheduleMapper.updateById(schedule);
// 查询同一排班、同一日期、序号大于当前取消预约的所有预约
QueryWrapper<Appointment> reorderWrapper = new QueryWrapper<>();
reorderWrapper.eq("schedule_id", appointment.getScheduleId())
.eq("appointment_date", appointmentDate)
.gt("queue_number", appointment.getQueueNumber())
.in("status", Arrays.asList(0, 1))
.orderByAsc("queue_number");
List<Appointment> needReorderList = appointmentMapper.selectList(reorderWrapper);
// 序号前移重新排序
for (Appointment app : needReorderList) {
int newQueueNumber = app.getQueueNumber() - 1;
app.setQueueNumber(newQueueNumber);
appointmentMapper.updateById(app);
// 通知患者序号变更
sendNotification(app.getUserId(),
"由于前序患者取消预约,您的就诊序号已更新为:" + newQueueNumber);
}
// 更新就诊历史状态
QueryWrapper<MedicalHistory> historyWrapper = new QueryWrapper<>();
historyWrapper.eq("appointment_id", appointmentId);
MedicalHistory history = medicalHistoryMapper.selectOne(historyWrapper);
if (history != null) {
history.setStatus(3); // 已取消
medicalHistoryMapper.updateById(history);
}
// 处理退款
if (refundAmount.compareTo(BigDecimal.ZERO) > 0) {
processRefund(userId, refundAmount, "预约取消退款");
cancelRecord.setStatus(1); // 已退款
cancelRecord.setRefundTime(now);
cancelAppointmentMapper.updateById(cancelRecord);
}
sendNotification(userId, "预约已取消," + refundDesc);
Map<String, Object> resultData = new HashMap<>();
resultData.put("refundAmount", refundAmount);
resultData.put("refundDesc", refundDesc);
return Result.success("预约取消成功", resultData);
}
六.系统文档展示
结束
💕💕文末获取源码联系 计算机程序员小杨