From 4a01825a309fe043686242ea5615e8b71c308981 Mon Sep 17 00:00:00 2001 From: wangjian963 <15215920+aprilry@user.noreply.gitee.com> Date: Thu, 30 Apr 2026 16:02:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=88=86=E8=AF=8A=E9=98=9F=E5=88=97):=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=88=86=E8=AF=8A=E9=98=9F=E5=88=97=E6=A0=B8?= =?UTF-8?q?=E5=BF=83=E5=8A=9F=E8=83=BD=E4=B8=8E=E6=97=A5=E5=BF=97=E8=AE=B0?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增分诊队列相关服务接口与实现,包括队列管理、叫号操作和日志记录 添加DivLogService和CallRecordService用于记录分诊操作和叫号历史 在CurrentDayEncounterDto和TriageQueueItem中增加seqNo字段用于显示预约序号 实现分诊操作日志记录功能,包括添加队列、移除队列、叫号、完成等操作 新增CallType枚举定义叫号类型,并实现叫号记录功能 优化队列状态映射逻辑,支持更多状态类型显示 --- .../OutpatientRegistrationAppServiceImpl.java | 7 +- .../impl/DoctorStationMainAppServiceImpl.java | 49 +++++---- .../impl/PaymentRecServiceImpl.java | 3 +- .../impl/TriageQueueAppServiceImpl.java | 102 ++++++++++-------- .../mapper/clinicalmanage/SurgeryMapper.xml | 2 +- .../common/enums/TriageQueueStatus.java | 35 ++++++ .../src/views/triageandqueuemanage/api.js | 3 +- .../triageandqueuemanage/cardiology/index.vue | 13 ++- 8 files changed, 139 insertions(+), 75 deletions(-) create mode 100644 openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/TriageQueueStatus.java diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java index d98c31f3..79840fc2 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java @@ -525,10 +525,11 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra ParticipantType.ADMITTER.getCode(), ParticipantType.REGISTRATION_DOCTOR.getCode(), queryWrapper, ChargeItemContext.REGISTER.getValue(), PaymentStatus.SUCCESS.getValue()); - // 过滤候选池排除列表(如果是从智能候选池查询,排除已加入队列的患者) - // 检查请求参数 excludeFromCandidatePool,如果为 true 或未设置,则过滤排除列表 + // 过滤候选池排除列表 + // 仅当调用方显式传 excludeFromCandidatePool=true 时才过滤,避免非分诊场景(挂号/收费) + // 因未传参导致默认过滤,使已入队患者不可见 String excludeParam = request.getParameter("excludeFromCandidatePool"); - boolean shouldExclude = excludeParam == null || "true".equalsIgnoreCase(excludeParam); + boolean shouldExclude = "true".equalsIgnoreCase(excludeParam); if (shouldExclude && currentDayEncounter != null && !currentDayEncounter.getRecords().isEmpty()) { try { // 获取当前租户和日期 diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java index 23efeb7b..6683ed67 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.core.common.core.domain.R; +import com.core.common.core.domain.model.LoginUser; import com.core.common.utils.AgeCalculatorUtil; import com.core.common.utils.SecurityUtils; import com.openhis.administration.domain.Encounter; @@ -17,7 +18,9 @@ import com.openhis.common.constant.CommonConstants; import com.openhis.common.enums.*; import com.openhis.common.utils.EnumUtils; import com.openhis.common.utils.HisQueryUtils; +import com.openhis.triageandqueuemanage.domain.DivLog; import com.openhis.triageandqueuemanage.domain.TriageQueueItem; +import com.openhis.triageandqueuemanage.service.DivLogService; import com.openhis.triageandqueuemanage.service.TriageQueueItemService; import com.openhis.web.doctorstation.appservice.*; import com.openhis.web.doctorstation.dto.PatientInfoDto; @@ -32,6 +35,7 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; import java.util.*; @@ -70,6 +74,10 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer @Resource private TriageQueueItemService triageQueueItemService; + + @Resource + private DivLogService divLogService; + /** * 查询就诊患者信息 * @@ -194,10 +202,13 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getEncounterId, encounterId) + // 限定当天日期,避免复诊患者匹配到历史队列记录 + .eq(TriageQueueItem::getQueueDate, LocalDate.now()) .eq(TriageQueueItem::getDeleteFlag, "0") ); if (queueItem != null) { - queueItem.setStatus(20); // 20=IN_CLINIC(诊中),患者进入诊室接诊 + // 使用 TriageQueueStatus 枚举替代原有硬编码数字 20,保证状态值一致性 + queueItem.setStatus(TriageQueueStatus.IN_CLINIC.getValue()); queueItem.setUpdateTime(LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)); triageQueueItemService.updateById(queueItem); log.info("接诊时更新队列状态为IN_CLINIC(诊中),encounterId={}, queueItemId={}", encounterId, queueItem.getId()); @@ -253,40 +264,38 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer return R.fail("非就诊中患者不能完诊"); } - // 2. 查找队列项 + // 2. 查找队列项(限定当天,避免复诊患者匹配到历史队列记录) Integer tenantId = SecurityUtils.getLoginUser().getTenantId(); TriageQueueItem queueItem = triageQueueItemService.getOne( new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getEncounterId, encounterId) + .eq(TriageQueueItem::getQueueDate, LocalDate.now()) .eq(TriageQueueItem::getDeleteFlag, "0") ); - // 如果队列项存在,检查状态并更新 - // 允许从 CALLING(10) 或 IN_CLINIC(20) 完成就诊 + // 如果队列项存在且未完成,更新队列状态为已完成 + // 使用排除法而非白名单:只要不是"已完成"就可以完诊,覆盖跳过、等待等非标准流转状态 if (queueItem != null && - (Integer.valueOf(10).equals(queueItem.getStatus()) || - Integer.valueOf(20).equals(queueItem.getStatus()))) { + !TriageQueueStatus.COMPLETED.getValue().equals(queueItem.getStatus())) { // 更新队列状态为已完成 java.time.LocalDateTime nowLocal = java.time.LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); - queueItem.setStatus(30); // 30=COMPLETED(已完成) + queueItem.setStatus(TriageQueueStatus.COMPLETED.getValue()); queueItem.setUpdateTime(nowLocal); triageQueueItemService.updateById(queueItem); - // 写入 div_log 审计日志 + // 写入 div_log 审计日志(使用实体+Service替代原生JDBC SQL,避免SQL注入风险,便于维护) try { - Long userId = SecurityUtils.getLoginUser().getUserId(); - String divLogSql = "INSERT INTO hisdev.div_log " - + "(pool_id, slot_id, queue_no, op_user_id, action, create_time) " - + "VALUES (?, ?, ?, ?, 30, NOW()::timestamp(0))"; - // action=30 表示 COMPLETED(已完成),与 triage_queue_item.status 数字编码保持一致 - // 0=WAITING, 10=CALLING, 20=IN_CLINIC, 30=COMPLETED, 40=SKIPPED, 50=REFUNDED, 60=FOLLOW - - jdbcTemplate.update(divLogSql, - queueItem.getPoolId(), // pool_id: 号源池ID(来自 adm_schedule_pool.id) - queueItem.getSlotId(), // slot_id: 号源槽位ID(来自 adm_schedule_slot.id) - queueItem.getQueueOrder(), // queue_no: 队列序号 - userId); // op_user_id: 操作用户ID + LoginUser loginUser = SecurityUtils.getLoginUser(); + DivLog divLog = new DivLog() + .setPoolId(queueItem.getPoolId()) + .setSlotId(queueItem.getSlotId()) + .setOpUserId(loginUser != null ? loginUser.getUserId() : null) + .setAction("COMPLETE") + .setCreateTime(LocalDateTime.now()) + .setUpdateAt(LocalDateTime.now()) + .setCreatedAt(LocalDateTime.now()); + divLogService.save(divLog); } catch (Exception e) { log.error("写入div_log审计日志失败", e); // 审计日志失败不影响主流程 diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/paymentmanage/appservice/impl/PaymentRecServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/paymentmanage/appservice/impl/PaymentRecServiceImpl.java index 62b3f358..3db5481e 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/paymentmanage/appservice/impl/PaymentRecServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/paymentmanage/appservice/impl/PaymentRecServiceImpl.java @@ -77,7 +77,6 @@ import com.openhis.yb.service.IClinicSettleService; import com.openhis.yb.service.IInpatientSettleService; import com.openhis.yb.service.IRegService; import com.openhis.yb.service.YbManager; -import com.openhis.web.triageandqueuemanage.appservice.impl.TriageQueueAppServiceImpl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.poi.util.StringUtil; @@ -2150,7 +2149,7 @@ public class PaymentRecServiceImpl implements IPaymentRecService { .setRoomNo(null) .setPoolId(queuePoolId) .setSlotId(queueSlotId) - .setStatus(TriageQueueAppServiceImpl.STATUS_WAITING) // 0=WAITING(等待中) + .setStatus(TriageQueueStatus.WAITING.getValue()) // 使用枚举替代硬编码常量,保持状态值一致 .setQueueOrder(maxOrder + 1) .setDeleteFlag("0") .setCreateTime(LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/triageandqueuemanage/appservice/impl/TriageQueueAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/triageandqueuemanage/appservice/impl/TriageQueueAppServiceImpl.java index 65794da2..58b6934a 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/triageandqueuemanage/appservice/impl/TriageQueueAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/triageandqueuemanage/appservice/impl/TriageQueueAppServiceImpl.java @@ -3,8 +3,14 @@ package com.openhis.web.triageandqueuemanage.appservice.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.core.common.core.domain.R; import com.core.common.utils.SecurityUtils; +import com.openhis.administration.domain.Encounter; +import com.openhis.administration.mapper.EncounterMapper; +import com.openhis.common.enums.EncounterStatus; +import com.openhis.common.enums.EncounterSubjectStatus; +import com.openhis.common.enums.TriageQueueStatus; import com.openhis.triageandqueuemanage.domain.CallRecord; import com.openhis.triageandqueuemanage.domain.DivLog; import com.openhis.triageandqueuemanage.domain.TriageCandidateExclusion; @@ -34,18 +40,8 @@ import java.util.stream.Collectors; @Service public class TriageQueueAppServiceImpl implements TriageQueueAppService { - /** - * 分诊队列状态常量(数字编码) - * 0=WAITING(等待中), 10=CALLING(呼叫中), 20=IN_CLINIC(诊中), - * 30=COMPLETED(已完成), 40=SKIPPED(已跳过), 50=REFUNDED(已退费), 60=FOLLOW(已随访) - */ - public static final Integer STATUS_WAITING = 0; - public static final Integer STATUS_CALLING = 10; - public static final Integer STATUS_IN_CLINIC = 20; - public static final Integer STATUS_COMPLETED = 30; - public static final Integer STATUS_SKIPPED = 40; - public static final Integer STATUS_REFUNDED = 50; - public static final Integer STATUS_FOLLOW = 60; + // 状态常量已迁移至 TriageQueueStatus 枚举,原硬编码 STATU_WAITING/STATU_CALLING 等已删除, + // 避免散落在多个 Service 类中的魔法数字造成不一致 @Resource private TriageQueueItemService triageQueueItemService; @@ -65,6 +61,9 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { @Resource private ScheduleSlotMapper scheduleSlotMapper; + @Resource + private EncounterMapper encounterMapper; + @Override public R list(Long organizationId, LocalDate date) { Integer tenantId = SecurityUtils.getLoginUser().getTenantId(); @@ -75,7 +74,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getQueueDate, qd) .eq(TriageQueueItem::getDeleteFlag, "0") - .ne(TriageQueueItem::getStatus, STATUS_COMPLETED) + .ne(TriageQueueItem::getStatus, TriageQueueStatus.COMPLETED.getValue()) .orderByAsc(TriageQueueItem::getQueueOrder); // 如果指定了科室,按科室过滤;否则查询所有科室(全科模式) @@ -98,7 +97,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { if (list != null && !list.isEmpty()) { int beforeSize = list.size(); list = list.stream() - .filter(item -> !STATUS_COMPLETED.equals(item.getStatus())) + .filter(item -> !TriageQueueStatus.COMPLETED.getValue().equals(item.getStatus())) .collect(java.util.stream.Collectors.toList()); } return R.ok(list); @@ -130,7 +129,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .eq(TriageQueueItem::getOrganizationId, orgId) .eq(TriageQueueItem::getQueueDate, qd) .eq(TriageQueueItem::getDeleteFlag, "0") - .ne(TriageQueueItem::getStatus, STATUS_COMPLETED)); + .ne(TriageQueueItem::getStatus, TriageQueueStatus.COMPLETED.getValue())); int maxOrder = existing.stream().map(TriageQueueItem::getQueueOrder).filter(Objects::nonNull).max(Integer::compareTo).orElse(0); @@ -155,7 +154,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .setPoolId(it.getPoolId()) // ✅ 号源池ID(用于div_log审计) .setSlotId(it.getSlotId()) // ✅ 号源槽位ID(用于div_log审计) .setSeqNo(it.getSeqNo()) // ✅ 预约序号(用于叫号显示) - .setStatus(STATUS_WAITING) + .setStatus(TriageQueueStatus.WAITING.getValue()) .setQueueOrder(++maxOrder) .setDeleteFlag("0") .setCreateTime(LocalDateTime.now()) @@ -285,8 +284,8 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { if (selected == null) return R.fail("队列项不存在"); // 只将"等待"状态的患者转为"叫号中",允许有多个"叫号中"的患者 - if (STATUS_WAITING.equals(selected.getStatus())) { - selected.setStatus(STATUS_CALLING).setUpdateTime(LocalDateTime.now()); + if (TriageQueueStatus.WAITING.getValue().equals(selected.getStatus())) { + selected.setStatus(TriageQueueStatus.CALLING.getValue()).setUpdateTime(LocalDateTime.now()); triageQueueItemService.updateById(selected); // 叫号后推送 SSE 消息(实时通知显示屏刷新) @@ -295,7 +294,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { writeDivLog(selected.getPoolId(), selected.getSlotId(), "CALL"); writeCallRecord(selected.getId(), selected.getPractitionerId(), CallType.CALL, selected.getRoomNo()); return R.ok(true); - } else if (STATUS_CALLING.equals(selected.getStatus())) { + } else if (TriageQueueStatus.CALLING.getValue().equals(selected.getStatus())) { // 如果已经是"叫号中"状态,直接返回成功(不做任何操作) return R.ok(true); } else { @@ -324,7 +323,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { return R.fail("队列项不存在"); } // 验证状态 - if (!STATUS_CALLING.equals(calling.getStatus())) { + if (!TriageQueueStatus.CALLING.getValue().equals(calling.getStatus())) { return R.fail("只能完成\"叫号中\"状态的患者,当前患者状态为:" + calling.getStatus()); } } else { @@ -334,7 +333,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { LambdaQueryWrapper callingWrapper = new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getDeleteFlag, "0") - .eq(TriageQueueItem::getStatus, STATUS_CALLING) + .eq(TriageQueueItem::getStatus, TriageQueueStatus.CALLING.getValue()) .orderByAsc(TriageQueueItem::getQueueOrder) .last("LIMIT 1"); @@ -353,16 +352,33 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { Long actualOrgId = calling.getOrganizationId(); // 1) 叫号中 -> 完成(移出列表) - calling.setStatus(STATUS_COMPLETED).setUpdateTime(LocalDateTime.now()); + calling.setStatus(TriageQueueStatus.COMPLETED.getValue()).setUpdateTime(LocalDateTime.now()); triageQueueItemService.updateById(calling); + // 同步更新就诊状态为诊毕 + // 分诊台完诊原只更新队列状态,未同步encounter表,导致与医生站完诊行为不一致 + if (calling.getEncounterId() != null) { + try { + java.util.Date now = new java.util.Date(); + encounterMapper.update(null, + new LambdaUpdateWrapper() + .eq(Encounter::getId, calling.getEncounterId()) + .set(Encounter::getStatusEnum, EncounterStatus.DISCHARGED.getValue()) + .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.DEPARTED.getValue()) + .set(Encounter::getEndTime, now) + .set(Encounter::getUpdateTime, now)); + } catch (Exception e) { + log.error("更新就诊状态为诊毕失败, encounterId={}", calling.getEncounterId(), e); + } + } + // 2) 自动推进下一个等待为叫号中(同一科室,包含跳过状态,不限制日期) LambdaQueryWrapper nextWrapper = new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getDeleteFlag, "0") - .and(w -> w.eq(TriageQueueItem::getStatus, STATUS_WAITING) + .and(w -> w.eq(TriageQueueItem::getStatus, TriageQueueStatus.WAITING.getValue()) .or() - .eq(TriageQueueItem::getStatus, STATUS_SKIPPED)) + .eq(TriageQueueItem::getStatus, TriageQueueStatus.SKIPPED.getValue())) .orderByAsc(TriageQueueItem::getQueueOrder) .last("LIMIT 1"); @@ -374,7 +390,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { TriageQueueItem next = triageQueueItemService.getOne(nextWrapper, false); if (next != null) { - next.setStatus(STATUS_CALLING).setUpdateTime(LocalDateTime.now()); + next.setStatus(TriageQueueStatus.CALLING.getValue()).setUpdateTime(LocalDateTime.now()); triageQueueItemService.updateById(next); } @@ -428,7 +444,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { return R.fail("队列项不存在"); } // 验证状态 - if (!STATUS_CALLING.equals(calling.getStatus())) { + if (!TriageQueueStatus.CALLING.getValue().equals(calling.getStatus())) { return R.fail("只能对\"叫号中\"状态的患者进行" + ("SKIP".equals(action) ? "跳过" : "过号重排") + ",当前患者状态为:" + calling.getStatus()); } } else { @@ -438,7 +454,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { LambdaQueryWrapper callingWrapper = new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getDeleteFlag, "0") - .eq(TriageQueueItem::getStatus, STATUS_CALLING) + .eq(TriageQueueItem::getStatus, TriageQueueStatus.CALLING.getValue()) .orderByAsc(TriageQueueItem::getQueueOrder) .last("LIMIT 1"); @@ -458,9 +474,9 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { LambdaQueryWrapper nextWrapper = new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getDeleteFlag, "0") - .and(w -> w.eq(TriageQueueItem::getStatus, STATUS_WAITING) + .and(w -> w.eq(TriageQueueItem::getStatus, TriageQueueStatus.WAITING.getValue()) .or() - .eq(TriageQueueItem::getStatus, STATUS_SKIPPED)) + .eq(TriageQueueItem::getStatus, TriageQueueStatus.SKIPPED.getValue())) .orderByAsc(TriageQueueItem::getQueueOrder) .last("LIMIT 1"); @@ -479,7 +495,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getOrganizationId, actualOrgId) .eq(TriageQueueItem::getDeleteFlag, "0") - .ne(TriageQueueItem::getStatus, STATUS_COMPLETED)) + .ne(TriageQueueItem::getStatus, TriageQueueStatus.COMPLETED.getValue())) .stream() .map(TriageQueueItem::getQueueOrder) .filter(Objects::nonNull) @@ -487,11 +503,11 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .orElse(0); // 1) 叫号中 -> 跳过,并移到末尾 - calling.setStatus(STATUS_SKIPPED).setQueueOrder(maxOrder + 1).setUpdateTime(LocalDateTime.now()); + calling.setStatus(TriageQueueStatus.SKIPPED.getValue()).setQueueOrder(maxOrder + 1).setUpdateTime(LocalDateTime.now()); triageQueueItemService.updateById(calling); // 2) 自动推进下一个等待为叫号中 - next.setStatus(STATUS_CALLING).setUpdateTime(LocalDateTime.now()); + next.setStatus(TriageQueueStatus.CALLING.getValue()).setUpdateTime(LocalDateTime.now()); triageQueueItemService.updateById(next); recalcOrders(actualOrgId, null); @@ -517,7 +533,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { return R.fail("队列项不存在"); } // 验证状态:必须是"叫号中"状态 - if (!STATUS_CALLING.equals(calling.getStatus())) { + if (!TriageQueueStatus.CALLING.getValue().equals(calling.getStatus())) { return R.fail("只能对\"叫号中\"状态的患者执行\"下一患者\"操作,当前患者状态为:" + calling.getStatus()); } } else { @@ -527,7 +543,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { LambdaQueryWrapper callingWrapper = new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getDeleteFlag, "0") - .eq(TriageQueueItem::getStatus, STATUS_CALLING) + .eq(TriageQueueItem::getStatus, TriageQueueStatus.CALLING.getValue()) .orderByAsc(TriageQueueItem::getQueueOrder) .last("LIMIT 1"); @@ -542,7 +558,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { // 当前叫号中 -> 完成(如果不存在,就当作从头找第一位等待) if (calling != null) { - calling.setStatus(STATUS_COMPLETED).setUpdateTime(LocalDateTime.now()); + calling.setStatus(TriageQueueStatus.COMPLETED.getValue()).setUpdateTime(LocalDateTime.now()); triageQueueItemService.updateById(calling); actualOrgId = calling.getOrganizationId(); // 使用叫号中患者所在的科室 } else { @@ -557,9 +573,9 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { LambdaQueryWrapper nextWrapper = new LambdaQueryWrapper() .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getDeleteFlag, "0") - .and(w -> w.eq(TriageQueueItem::getStatus, STATUS_WAITING) + .and(w -> w.eq(TriageQueueItem::getStatus, TriageQueueStatus.WAITING.getValue()) .or() - .eq(TriageQueueItem::getStatus, STATUS_SKIPPED)) + .eq(TriageQueueItem::getStatus, TriageQueueStatus.SKIPPED.getValue())) .orderByAsc(TriageQueueItem::getQueueOrder) .last("LIMIT 1"); @@ -576,7 +592,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { return R.fail("当前没有等待的患者"); } - next.setStatus(STATUS_CALLING).setUpdateTime(LocalDateTime.now()); + next.setStatus(TriageQueueStatus.CALLING.getValue()).setUpdateTime(LocalDateTime.now()); triageQueueItemService.updateById(next); if (next.getOrganizationId() != null) { @@ -598,7 +614,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .eq(TriageQueueItem::getTenantId, tenantId) .eq(TriageQueueItem::getOrganizationId, orgId) .eq(TriageQueueItem::getDeleteFlag, "0") - .ne(TriageQueueItem::getStatus, STATUS_COMPLETED); + .ne(TriageQueueItem::getStatus, TriageQueueStatus.COMPLETED.getValue()); // 如果 qd 不为 null,才添加日期限制 if (qd != null) { wrapper.eq(TriageQueueItem::getQueueDate, qd); @@ -613,7 +629,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .eq(TriageQueueItem::getOrganizationId, orgId) .eq(TriageQueueItem::getQueueDate, qd) .eq(TriageQueueItem::getDeleteFlag, "0") - .eq(TriageQueueItem::getStatus, STATUS_CALLING) + .eq(TriageQueueItem::getStatus, TriageQueueStatus.CALLING.getValue()) .last("LIMIT 1"), false); } @@ -658,7 +674,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { .eq(TriageQueueItem::getQueueDate, qd) .eq(TriageQueueItem::getOrganizationId, organizationId) .eq(TriageQueueItem::getTenantId, tenantId) - .in(TriageQueueItem::getStatus, STATUS_WAITING, STATUS_CALLING) + .in(TriageQueueItem::getStatus, TriageQueueStatus.WAITING.getValue(), TriageQueueStatus.CALLING.getValue()) .eq(TriageQueueItem::getDeleteFlag, "0") .orderByAsc(TriageQueueItem::getQueueOrder) ); @@ -677,7 +693,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { // 2. 查找当前叫号中的患者(CALLING 状态) TriageQueueItem callingItem = allItems.stream() - .filter(item -> STATUS_CALLING.equals(item.getStatus())) + .filter(item -> TriageQueueStatus.CALLING.getValue().equals(item.getStatus())) .findFirst() .orElse(null); @@ -742,7 +758,7 @@ public class TriageQueueAppServiceImpl implements TriageQueueAppService { patients.add(patient); // 统计等待人数(不包括 CALLING 状态) - if (STATUS_WAITING.equals(item.getStatus())) { + if (TriageQueueStatus.WAITING.getValue().equals(item.getStatus())) { totalWaiting++; } } diff --git a/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml b/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml index 17c94402..f738db11 100644 --- a/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml +++ b/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml @@ -339,7 +339,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" AND sr.id IS NULL diff --git a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/TriageQueueStatus.java b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/TriageQueueStatus.java new file mode 100644 index 00000000..928824ce --- /dev/null +++ b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/TriageQueueStatus.java @@ -0,0 +1,35 @@ +package com.openhis.common.enums; + +import com.baomidou.mybatisplus.annotation.EnumValue; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 智能分诊队列状态 + */ +@Getter +@AllArgsConstructor +public enum TriageQueueStatus implements HisEnumInterface { + WAITING(0, "waiting", "等待"), + CALLING(10, "calling", "叫号中"), + IN_CLINIC(20, "in-clinic", "就诊中"), + COMPLETED(30, "completed", "完成"), + SKIPPED(40, "skipped", "跳过"); + + @EnumValue + private final Integer value; + private final String code; + private final String info; + + public static TriageQueueStatus getByValue(Integer value) { + if (value == null) { + return null; + } + for (TriageQueueStatus val : values()) { + if (val.getValue().equals(value)) { + return val; + } + } + return null; + } +} diff --git a/openhis-ui-vue3/src/views/triageandqueuemanage/api.js b/openhis-ui-vue3/src/views/triageandqueuemanage/api.js index 117f4022..aabf67a4 100644 --- a/openhis-ui-vue3/src/views/triageandqueuemanage/api.js +++ b/openhis-ui-vue3/src/views/triageandqueuemanage/api.js @@ -37,7 +37,8 @@ export function getCandidatePool(params) { pageNo: params?.pageNo || 1, pageSize: params?.pageSize || 10000, searchKey: params?.searchKey || '', - statusEnum: params?.statusEnum ?? 1 // 1=PLANNED(待诊),已挂号未接诊的患者;不传或传-1会返回已接诊的患者 + statusEnum: params?.statusEnum ?? 1, // 1=PLANNED(待诊),已挂号未接诊的患者 + excludeFromCandidatePool: true // 显式传参过滤已入队患者,配合后端 opt-in 逻辑 }, skipErrorMsg: true // 跳过错误提示,由组件处理 }) diff --git a/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue b/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue index 0a19dfce..bb59b825 100644 --- a/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue +++ b/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue @@ -840,7 +840,8 @@ const syncCurrentCallFromQueue = () => { return } currentCall.value = { - number: String(calling.queueOrder), + // 优先显示预约序号 seqNo,让患者凭挂号单号识别;无预约序号时回退到排队序号 + number: String(calling.seqNo ?? calling.queueOrder), name: calling.patientName, room: calling.room } @@ -877,7 +878,7 @@ const mapBackendStatusToFrontend = (status) => { switch (numStatus) { case 0: return '等待' case 10: return '叫号中' - case 20: return '诊中' + case 20: return '就诊中' // 统一文案,与医生站"就诊中"保持一致,原"诊中"过于简略 case 30: return '已完成' case 40: return '跳过' case 50: return '已退费' @@ -894,7 +895,7 @@ const mapFrontendStatusToBackend = (status) => { switch (status) { case '叫号中': return 10 case '等待': return 0 - case '诊中': return 20 + case '就诊中': return 20 case '已完成': return 30 case '跳过': return 40 case '已退费': return 50 @@ -960,6 +961,8 @@ const loadQueueFromDb = async () => { return { id: it.id, queueOrder: it.queueOrder, + // 预约序号,优先于queueOrder用于叫号屏显示,患者凭此识别 + seqNo: it.seqNo, patientName: it.patientName ?? '-', // 队列数据已从入队时存储的 healthcareName 读取(包含"预约"或"挂号"后缀) appointmentType: it.healthcareName ?? '普通号挂号', @@ -1715,8 +1718,8 @@ const handleSelectCall = async () => { const latest = originalQueueList.value.find((i) => i.id === selectedQueueRow.value.id) if (latest) { selectedQueueRow.value = latest - // 如果有多个"叫号中"的患者,显示当前选中的这个 - currentCall.value = { number: String(latest.queueOrder), name: latest.patientName, room: latest.room } + // 如果有多个"叫号中"的患者,显示当前选中的这个,seqNo优先于queueOrder + currentCall.value = { number: String(latest.seqNo ?? latest.queueOrder), name: latest.patientName, room: latest.room } } // 统计当前"叫号中"的患者数量