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 5d022053..75a1010d 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 @@ -1,6 +1,7 @@ package com.openhis.web.doctorstation.appservice.impl; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -16,21 +17,23 @@ 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.TriageQueueItem; +import com.openhis.triageandqueuemanage.service.TriageQueueItemService; import com.openhis.web.doctorstation.appservice.*; import com.openhis.web.doctorstation.dto.PatientInfoDto; import com.openhis.web.doctorstation.dto.PrescriptionInfoBaseDto; import com.openhis.web.doctorstation.dto.PrescriptionInfoDetailDto; import com.openhis.web.doctorstation.dto.ReceptionStatisticsDto; import com.openhis.web.doctorstation.mapper.DoctorStationMainAppMapper; +import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; - -import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; @@ -64,6 +67,9 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer @Resource private JdbcTemplate jdbcTemplate; + + @Resource + private TriageQueueItemService triageQueueItemService; /** * 查询就诊患者信息 * @@ -124,14 +130,40 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer * @return 结果 */ @Override + @Transactional(rollbackFor = Exception.class) public R receiveEncounter(Long encounterId) { Integer tenantId = SecurityUtils.getLoginUser().getTenantId(); String currentUsername = SecurityUtils.getUsername(); + + // 检查就诊记录是否存在 + Encounter encounter = encounterMapper.selectById(encounterId); + if (encounter == null) { + return R.fail("就诊记录不存在"); + } + + // 检查患者状态,防止重复接诊 + Integer currentStatus = encounter.getStatusEnum(); + if (EncounterStatus.IN_PROGRESS.getValue().equals(currentStatus)) { + return R.fail("已接诊,请勿重复点击,已为您刷新"); + } + int update = encounterMapper.update(null, new LambdaUpdateWrapper().eq(Encounter::getId, encounterId) + .eq(Encounter::getStatusEnum, EncounterStatus.PLANNED.getValue()) // 只更新待诊状态的患者 .set(Encounter::getReceptionTime, new Date()) .set(Encounter::getStatusEnum, EncounterStatus.IN_PROGRESS.getValue()) .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.RECEIVING_CARE.getValue())); + + // 如果更新失败,说明状态已被其他医生修改 + if (update <= 0) { + // 重新查询当前状态 + encounter = encounterMapper.selectById(encounterId); + if (EncounterStatus.IN_PROGRESS.getValue().equals(encounter.getStatusEnum())) { + return R.fail("已接诊,请勿重复接诊"); + } + return R.fail("接诊失败,请刷新后重试"); + } + // 先把之前的接诊记录更新为已完成 iEncounterParticipantService.update(new LambdaUpdateWrapper() .eq(EncounterParticipant::getTypeCode, ParticipantType.ADMITTER.getCode()) @@ -148,7 +180,28 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer encounterParticipant.setCreateBy(currentUsername); encounterParticipant.setCreateTime(new Date()); iEncounterParticipantService.save(encounterParticipant); - return update > 0 ? R.ok() : R.fail(); + + // 更新 triage_queue_item 队列记录状态为 CALLING + try { + TriageQueueItem queueItem = triageQueueItemService.getOne( + new LambdaQueryWrapper() + .eq(TriageQueueItem::getTenantId, tenantId) + .eq(TriageQueueItem::getEncounterId, encounterId) + .eq(TriageQueueItem::getDeleteFlag, "0") + ); + if (queueItem != null) { + queueItem.setStatus("CALLING"); + queueItem.setUpdateTime(LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)); + triageQueueItemService.updateById(queueItem); + log.info("接诊时更新队列状态为CALLING,encounterId={}, queueItemId={}", encounterId, queueItem.getId()); + } else { + log.warn("接诊时未找到队列记录,encounterId={}", encounterId); + } + } catch (Exception e) { + log.error("接诊时更新队列状态失败,encounterId={}", encounterId, e); + } + + return R.ok(); } /** @@ -181,11 +234,54 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer return R.fail("就诊记录不存在"); } - if (!EncounterStatus.IN_PROGRESS.getValue().equals(encounter.getStatusEnum())) { - return R.fail("当前患者不在就诊中状态"); + // 检查患者状态,防止重复完诊 + Integer currentStatus = encounter.getStatusEnum(); + if (EncounterStatus.DISCHARGED.getValue().equals(currentStatus) || + EncounterStatus.COMPLETED.getValue().equals(currentStatus)) { + // 患者已完成就诊,返回特定提示 + return R.fail("患者已完成就诊,已为您自动刷新患者列表"); } - // 2. 更新状态、完成时间以及初复诊标识 + if (!EncounterStatus.IN_PROGRESS.getValue().equals(currentStatus)) { + return R.fail("非就诊中患者不能完诊"); + } + + // 2. 查找队列项 + Integer tenantId = SecurityUtils.getLoginUser().getTenantId(); + TriageQueueItem queueItem = triageQueueItemService.getOne( + new LambdaQueryWrapper() + .eq(TriageQueueItem::getTenantId, tenantId) + .eq(TriageQueueItem::getEncounterId, encounterId) + .eq(TriageQueueItem::getDeleteFlag, "0") + ); + + // 如果队列项存在,检查状态并更新 + if (queueItem != null && "CALLING".equals(queueItem.getStatus())) { + // 更新队列状态为已完成 + java.time.LocalDateTime nowLocal = java.time.LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); + queueItem.setStatus("COMPLETED"); + queueItem.setUpdateTime(nowLocal); + triageQueueItemService.updateById(queueItem); + + // 写入 div_log 审计日志 + 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 (?, ?, ?, ?, 'COMPLETE', NOW()::timestamp(0))"; + + jdbcTemplate.update(divLogSql, + queueItem.getOrganizationId(), // pool_id: 候选池ID(科室) + queueItem.getPractitionerId(), // slot_id: 槽位ID(医生) + queueItem.getQueueOrder(), // queue_no: 队列号 + userId); // op_user_id: 操作用户ID + } catch (Exception e) { + log.error("写入div_log审计日志失败", e); + // 审计日志失败不影响主流程 + } + } + + // 3. 更新状态、完成时间以及初复诊标识 Date now = new Date(); int update = encounterMapper.update(null, new LambdaUpdateWrapper() @@ -198,7 +294,7 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer if (update <= 0) return R.fail("完诊失败"); - // 3. 审计日志 + // 4. 审计日志(sys_oper_log) try { String username = SecurityUtils.getUsernameSafe(); String sql = "INSERT INTO sys_oper_log " 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 aee60702..5d24d3d6 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 @@ -55,6 +55,8 @@ import com.openhis.web.paymentmanage.dto.CancelPaymentDto; import com.openhis.web.paymentmanage.dto.Clinic2207OrderResultDto; import com.openhis.web.paymentmanage.mapper.PaymentMapper; import com.openhis.web.personalization.dto.ActivityDeviceDto; +import com.openhis.triageandqueuemanage.domain.TriageQueueItem; +import com.openhis.triageandqueuemanage.service.TriageQueueItemService; import com.openhis.workflow.domain.ServiceRequest; import com.openhis.workflow.service.IDeviceDispenseService; import com.openhis.workflow.service.IDeviceRequestService; @@ -81,9 +83,11 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.math.RoundingMode; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; @@ -149,6 +153,8 @@ public class PaymentRecServiceImpl implements IPaymentRecService { @Resource private OutpatientRegistrationAppMapper outpatientRegistrationAppMapper; @Resource + private TriageQueueItemService triageQueueItemService; + @Resource private IRegService iRegService; @Resource private IPatientService iPatientService; @@ -1928,6 +1934,80 @@ public class PaymentRecServiceImpl implements IPaymentRecService { // 就诊ID Long encounterId = iEncounterService.saveEncounterByRegister(encounter); + + // 创建 triage_queue_item 队列记录 + try { + Integer tenantId = encounter.getTenantId() != null ? encounter.getTenantId() : SecurityUtils.getLoginUser().getTenantId(); + LocalDate queueDate = LocalDate.now(); + + // 查询当前科室当天的最大排队序号 + Integer maxOrder = triageQueueItemService.list( + new LambdaQueryWrapper() + .eq(TriageQueueItem::getTenantId, tenantId) + .eq(TriageQueueItem::getOrganizationId, encounter.getOrganizationId()) + .eq(TriageQueueItem::getQueueDate, queueDate) + .eq(TriageQueueItem::getDeleteFlag, "0") + .ne(TriageQueueItem::getStatus, "COMPLETED") + ).stream() + .map(TriageQueueItem::getQueueOrder) + .filter(Objects::nonNull) + .max(Integer::compareTo) + .orElse(0); + + // 获取患者信息 + Patient patient = iPatientService.getById(encounter.getPatientId()); + String patientName = patient != null ? patient.getName() : null; + + // 获取挂号医生信息 + String practitionerName = null; + Long queuePractitionerId = null; + if (encounterParticipantFormData.getPractitionerId() != null) { + Practitioner practitioner = iPractitionerService.getById(encounterParticipantFormData.getPractitionerId()); + if (practitioner != null) { + practitionerName = practitioner.getName(); + queuePractitionerId = practitioner.getId(); + } + } + + // 获取科室信息 + Organization organization = iOrganizationService.getById(encounter.getOrganizationId()); + String organizationName = organization != null ? organization.getName() : null; + + // 获取服务项目信息(挂号类型) + String healthcareName = null; + if (encounter.getServiceTypeId() != null) { + HealthcareService healthcareService = healthcareServiceService.getById(encounter.getServiceTypeId()); + if (healthcareService != null) { + healthcareName = healthcareService.getName(); + } + } + + // 创建队列项 + TriageQueueItem queueItem = new TriageQueueItem() + .setTenantId(tenantId) + .setQueueDate(queueDate) + .setOrganizationId(encounter.getOrganizationId()) + .setOrganizationName(organizationName) + .setEncounterId(encounterId) + .setPatientId(encounter.getPatientId()) + .setPatientName(patientName) + .setHealthcareName(healthcareName) + .setPractitionerId(queuePractitionerId) + .setPractitionerName(practitionerName) + .setRoomNo(null) + .setStatus("WAITING") + .setQueueOrder(maxOrder + 1) + .setDeleteFlag("0") + .setCreateTime(LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)) + .setUpdateTime(LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS)); + + triageQueueItemService.save(queueItem); + logger.info("挂号时创建队列记录成功,encounterId={}, queueItemId={}", encounterId, queueItem.getId()); + } catch (Exception e) { + logger.error("挂号时创建队列记录失败,encounterId={}", encounterId, e); + // 队列记录创建失败不影响挂号流程 + } + // 保存就诊位置信息 // 挂号时不选Location了 // encounterLocationFormData.setEncounterId(encounterId); diff --git a/openhis-ui-vue3/src/views/doctorstation/components/patientList.vue b/openhis-ui-vue3/src/views/doctorstation/components/patientList.vue index 97b35a3e..460ebec1 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/patientList.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/patientList.vue @@ -140,6 +140,12 @@ function handleReceive(row) { // } receiveEncounter(row.encounterId).then(() => { emits('toCurrent', row); + }).catch(error => { + // 如果接诊失败,检查是否是"已接诊"的错误 + if (error && error.message && error.message.includes('已接诊')) { + // 自动刷新列表,移除已接诊的患者 + getPatientList(); + } }); } diff --git a/openhis-ui-vue3/src/views/doctorstation/index.vue b/openhis-ui-vue3/src/views/doctorstation/index.vue index b7cc09ac..521765c9 100644 --- a/openhis-ui-vue3/src/views/doctorstation/index.vue +++ b/openhis-ui-vue3/src/views/doctorstation/index.vue @@ -168,7 +168,7 @@
- + { + // 如果完诊失败,检查是否是"已完成"的错误 + if (error && error.message && (error.message.includes('已完成') || error.message.includes('完诊'))) { + // 自动刷新现诊患者列表 + getPatientList(); + } }); }