diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java index 43b6cbbd..c5c8c1da 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java @@ -1,8 +1,10 @@ package com.openhis.web.appointmentmanage.appservice.impl; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.common.core.domain.R; import com.core.common.utils.SecurityUtils; +import com.openhis.common.constant.CommonConstants; import com.openhis.appointmentmanage.domain.DoctorSchedule; import com.openhis.appointmentmanage.domain.DoctorScheduleWithDateDto; import com.openhis.appointmentmanage.domain.SchedulePool; @@ -497,6 +499,15 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService { if (ObjectUtil.isNotEmpty(pools)) { List poolIds = pools.stream().map(SchedulePool::getId).collect(java.util.stream.Collectors.toList()); + // 该排班下存在有效患者预约(号源槽:已预约/已锁定/已取号)则禁止删除;已退号、仅可用/已取消槽位不计入 + long appointmentCount = scheduleSlotService.count(new QueryWrapper() + .in("pool_id", poolIds) + .in("status", CommonConstants.SlotStatus.BOOKED, CommonConstants.SlotStatus.LOCKED, + CommonConstants.SlotStatus.CHECKED_IN)); + if (appointmentCount > 0) { + return R.fail("该排班已有患者预约,禁止删除!如需取消请先处理患者退预约或使用'停诊'功能。"); + } + // 2. 根据号源池ID找到所有关联的号源槽 List slots = scheduleSlotService.list( new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper() diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java index 4de68bf2..50826897 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java @@ -2,6 +2,7 @@ package com.openhis.web.clinicalmanage.dto; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.fasterxml.jackson.annotation.JsonFormat; import com.openhis.common.annotation.Dict; import lombok.Data; import lombok.experimental.Accessors; @@ -87,6 +88,7 @@ public class SurgeryDto { private String statusEnum_dictText; /** 计划手术时间 */ + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "GMT+8") private Date plannedTime; /** 实际开始时间 */ diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/consultation/appservice/impl/ConsultationAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/consultation/appservice/impl/ConsultationAppServiceImpl.java index f3d04340..ac034051 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/consultation/appservice/impl/ConsultationAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/consultation/appservice/impl/ConsultationAppServiceImpl.java @@ -1365,10 +1365,13 @@ public class ConsultationAppServiceImpl implements IConsultationAppService { } // 4. 更新邀请记录(存储会诊意见) - // 格式:科室-医生:意见内容 + // 格式:科室-会诊确认参加医师:意见内容 + // 兼容:若前端未填写“会诊确认参加医师”,则回退为当前医生姓名 + String confirmingPhysicianText = + StringUtils.hasText(dto.getConfirmingPhysician()) ? dto.getConfirmingPhysician().trim() : currentPhysicianName; String formattedOpinion = String.format("%s-%s:%s", currentDeptName, - currentPhysicianName, + confirmingPhysicianText, dto.getConsultationOpinion()); invited.setInvitedStatus(ConsultationStatusEnum.CONFIRMED.getCode()); // 已确认 diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java index b5fab5da..5d106a20 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java @@ -42,4 +42,20 @@ public interface OrderMapper extends BaseMapper { * @return 结果 */ int updatePayStatus(@Param("orderId") Long orderId, @Param("payStatus") Integer payStatus, @Param("payTime") Date payTime); + + /** + * 统计同一患者在同一科室、同一时段(上午/下午)内的有效预约订单数量 + * + * @param patientId 患者ID + * @param departmentId 科室ID + * @param startTime 时段起始时间(含) + * @param endTime 时段结束时间(不含) + * @param statuses 订单状态集合(如 1=已预约,2=已取号) + * @return 数量 + */ + int countPatientDeptOrdersInPeriod(@Param("patientId") Long patientId, + @Param("departmentId") Long departmentId, + @Param("startTime") Date startTime, + @Param("endTime") Date endTime, + @Param("statuses") List statuses); } diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java index c8f0f5f9..95bc8101 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java @@ -28,6 +28,7 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.temporal.TemporalAdjusters; import java.util.Date; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -182,6 +183,28 @@ public class TicketServiceImpl extends ServiceImpl impleme throw new RuntimeException("该排班医生已停诊"); } + // 2.1 同一患者同一天/同一科室/同一时段(上午/下午)不可重复预约 + if (dto.getPatientId() != null && slot.getDepartmentId() != null && slot.getScheduleDate() != null && slot.getExpectTime() != null) { + boolean isMorning = slot.getExpectTime().isBefore(LocalTime.NOON); + LocalDate scheduleDateForCheck = slot.getScheduleDate(); + LocalDateTime periodStart = isMorning + ? LocalDateTime.of(scheduleDateForCheck, LocalTime.MIN) + : LocalDateTime.of(scheduleDateForCheck, LocalTime.NOON); + LocalDateTime periodEnd = isMorning + ? LocalDateTime.of(scheduleDateForCheck, LocalTime.NOON) + : LocalDateTime.of(scheduleDateForCheck.plusDays(1), LocalTime.MIN); + + Date startTime = Date.from(periodStart.atZone(ZoneId.systemDefault()).toInstant()); + Date endTime = Date.from(periodEnd.atZone(ZoneId.systemDefault()).toInstant()); + + // 预约去重以订单为准(order_main),因为预约成功会先落订单;clinical_ticket 不一定在此链路写入 + List effectiveOrderStatuses = Arrays.asList(AppointmentOrderStatus.BOOKED, AppointmentOrderStatus.CHECKED_IN); + int exists = orderMapper.countPatientDeptOrdersInPeriod(dto.getPatientId(), slot.getDepartmentId(), startTime, endTime, effectiveOrderStatuses); + if (exists > 0) { + throw new RuntimeException("该患者已在当前科室该时段存在预约记录,不可重复预约"); + } + } + // 原子抢占:避免并发下同一槽位被重复预约 int lockRows = scheduleSlotMapper.lockSlotForBooking(slotId); if (lockRows <= 0) { @@ -264,9 +287,6 @@ public class TicketServiceImpl extends ServiceImpl impleme throw new RuntimeException("当前号源没有可取消的预约订单"); } - // 获取订单信息 - Order latestOrder = orders.get(0); - // 直接执行取消,不再检查取消限制 // 根据需求,取消限制应在预约挂号时检查,而非取消预约时 for (Order order : orders) { diff --git a/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml b/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml index 52580888..c3212215 100644 --- a/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml +++ b/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml @@ -217,6 +217,23 @@ where id = #{id} + + update order_main set status = #{status} where id = #{id} diff --git a/openhis-ui-vue3/src/views/consultationmanagement/consultationconfirmation/index.vue b/openhis-ui-vue3/src/views/consultationmanagement/consultationconfirmation/index.vue index ab7a14cf..53000b95 100644 --- a/openhis-ui-vue3/src/views/consultationmanagement/consultationconfirmation/index.vue +++ b/openhis-ui-vue3/src/views/consultationmanagement/consultationconfirmation/index.vue @@ -352,7 +352,20 @@ const applyRowToForm = (row) => { if (myOpinion) { // 如果当前医生已确认,回显其信息 - formData.value.confirmingPhysician = myOpinion.physicianName || '' + // 回显“会诊确认参加医师”:优先从 opinion 前缀解析(格式:科室-参加医师:意见) + // 兼容旧数据(格式:科室-医生:意见)以及异常格式 + if (myOpinion.opinion) { + const opinionText = myOpinion.opinion + const colonIndex = opinionText.indexOf(':') + const dashIndex = opinionText.indexOf('-') + if (dashIndex >= 0 && colonIndex > dashIndex) { + formData.value.confirmingPhysician = opinionText.substring(dashIndex + 1, colonIndex).trim() + } else { + formData.value.confirmingPhysician = myOpinion.physicianName || '' + } + } else { + formData.value.confirmingPhysician = myOpinion.physicianName || '' + } formData.value.confirmingPhysicianName = myOpinion.physicianName formData.value.confirmingDeptName = myOpinion.deptName