Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a844920e3f | ||
|
|
b02c6f6456 | ||
|
|
9e2d683e19 | ||
|
|
51f4b84842 | ||
|
|
c0ea55a74d | ||
|
|
7990247a97 | ||
|
|
94a6f9553c | ||
|
|
bef429df0c | ||
|
|
aaaf548003 | ||
|
|
d61373593e | ||
|
|
d2699f5cdd | ||
|
|
7deba511d4 | ||
|
|
3fed829cc8 | ||
|
|
5cbaee98f7 | ||
|
|
d4da94c400 | ||
|
|
3103c619f2 |
@@ -10,7 +10,7 @@ import com.openhis.clinical.service.ITicketService;
|
|||||||
import com.openhis.web.appointmentmanage.appservice.ITicketAppService;
|
import com.openhis.web.appointmentmanage.appservice.ITicketAppService;
|
||||||
import com.openhis.web.appointmentmanage.dto.TicketDto;
|
import com.openhis.web.appointmentmanage.dto.TicketDto;
|
||||||
import com.openhis.common.constant.CommonConstants.SlotStatus;
|
import com.openhis.common.constant.CommonConstants.SlotStatus;
|
||||||
import com.openhis.common.enums.OrderStatus;
|
import com.openhis.common.constant.CommonConstants.AppointmentOrderStatus;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -198,11 +198,10 @@ public class TicketAppServiceImpl implements ITicketAppService {
|
|||||||
if (SlotStatus.CHECKED_IN.equals(slotStatus)) {
|
if (SlotStatus.CHECKED_IN.equals(slotStatus)) {
|
||||||
dto.setStatus("已取号");
|
dto.setStatus("已取号");
|
||||||
} else if (SlotStatus.BOOKED.equals(slotStatus)) {
|
} else if (SlotStatus.BOOKED.equals(slotStatus)) {
|
||||||
// order_main.status: 0=患者取消(已退号) 2=系统取消 其余=已预约
|
if (AppointmentOrderStatus.CHECKED_IN.equals(raw.getOrderStatus())) {
|
||||||
if (OrderStatus.PATIENT_CANCELLED.getValue().equals(raw.getOrderStatus())) {
|
dto.setStatus("已取号");
|
||||||
|
} else if (AppointmentOrderStatus.RETURNED.equals(raw.getOrderStatus())) {
|
||||||
dto.setStatus("已退号");
|
dto.setStatus("已退号");
|
||||||
} else if (OrderStatus.SYSTEM_CANCELLED.getValue().equals(raw.getOrderStatus())) {
|
|
||||||
dto.setStatus("系统取消");
|
|
||||||
} else {
|
} else {
|
||||||
dto.setStatus("已预约");
|
dto.setStatus("已预约");
|
||||||
}
|
}
|
||||||
@@ -373,11 +372,10 @@ public class TicketAppServiceImpl implements ITicketAppService {
|
|||||||
if (SlotStatus.CHECKED_IN.equals(slotStatus)) {
|
if (SlotStatus.CHECKED_IN.equals(slotStatus)) {
|
||||||
dto.setStatus("已取号");
|
dto.setStatus("已取号");
|
||||||
} else if (SlotStatus.BOOKED.equals(slotStatus)) {
|
} else if (SlotStatus.BOOKED.equals(slotStatus)) {
|
||||||
// order_main.status: 0=患者取消(已退号) 2=系统取消 其余=已预约
|
if (AppointmentOrderStatus.CHECKED_IN.equals(raw.getOrderStatus())) {
|
||||||
if (OrderStatus.PATIENT_CANCELLED.getValue().equals(raw.getOrderStatus())) {
|
dto.setStatus("已取号");
|
||||||
|
} else if (AppointmentOrderStatus.RETURNED.equals(raw.getOrderStatus())) {
|
||||||
dto.setStatus("已退号");
|
dto.setStatus("已退号");
|
||||||
} else if (OrderStatus.SYSTEM_CANCELLED.getValue().equals(raw.getOrderStatus())) {
|
|
||||||
dto.setStatus("系统取消");
|
|
||||||
} else {
|
} else {
|
||||||
dto.setStatus("已预约");
|
dto.setStatus("已预约");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.openhis.web.chargemanage.appservice.impl;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.core.common.core.domain.R;
|
import com.core.common.core.domain.R;
|
||||||
@@ -330,14 +329,16 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 退费成功后,同步回滚预约订单状态及号源;同时移除分诊队列
|
// 如果本次门诊挂号来自预约签到,同步把预约订单与号源槽位状态改为已退号
|
||||||
Long refundOrderMainId = null;
|
|
||||||
if (result != null && result.getCode() == 200) {
|
if (result != null && result.getCode() == 200) {
|
||||||
refundOrderMainId = syncAppointmentReturnStatus(byId, cancelRegPaymentDto.getReason());
|
syncAppointmentReturnStatus(byId, cancelRegPaymentDto.getReason());
|
||||||
|
|
||||||
|
// 同步移除分诊队列中的记录
|
||||||
removeTriageQueueItem(byId.getId());
|
removeTriageQueueItem(byId.getId());
|
||||||
}
|
}
|
||||||
// 退号日志独立事务写入,无论退费成功与否均记录
|
|
||||||
recordRefundLog(cancelRegPaymentDto, byId, result, paymentRecon, refundOrderMainId);
|
// 记录退号日志
|
||||||
|
recordRefundLog(cancelRegPaymentDto, byId, result, paymentRecon);
|
||||||
|
|
||||||
// 2025/05/05 该处保存费用项后,会通过统一收费处理进行收费
|
// 2025/05/05 该处保存费用项后,会通过统一收费处理进行收费
|
||||||
return R.ok(paymentRecon, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"退号"}));
|
return R.ok(paymentRecon, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"退号"}));
|
||||||
@@ -434,6 +435,8 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
|
|||||||
// 通过患者、科室、日期查找关联的预约订单
|
// 通过患者、科室、日期查找关联的预约订单
|
||||||
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<Order>()
|
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<Order>()
|
||||||
.eq(Order::getPatientId, encounter.getPatientId())
|
.eq(Order::getPatientId, encounter.getPatientId())
|
||||||
|
.in(Order::getStatus, CommonConstants.AppointmentOrderStatus.BOOKED,
|
||||||
|
CommonConstants.AppointmentOrderStatus.CHECKED_IN)
|
||||||
.orderByDesc(Order::getUpdateTime)
|
.orderByDesc(Order::getUpdateTime)
|
||||||
.orderByDesc(Order::getCreateTime)
|
.orderByDesc(Order::getCreateTime)
|
||||||
.last("LIMIT 1");
|
.last("LIMIT 1");
|
||||||
@@ -587,25 +590,20 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 诊前退号:回滚预约订单、号源槽位、号源池统计。
|
* 同步预约号源状态为已退号。
|
||||||
*
|
* 说明:
|
||||||
* <p>处理四件事:
|
* 1) 门诊退号主流程不依赖该步骤成功与否,因此此方法内部异常仅记录日志,不向上抛出。
|
||||||
* <ol>
|
* 2) 通过患者、科室、日期以及状态筛选最近一条预约订单,尽量避免误匹配。
|
||||||
* <li>order_main → status=0(患者取消), pay_status=3(已退费), 写入取消时间和原因</li>
|
|
||||||
* <li>adm_schedule_slot → status=0(待约), order_id=NULL(释放号源)</li>
|
|
||||||
* <li>adm_schedule_pool → 重算统计值 + version+1</li>
|
|
||||||
* <li>返回 order_main.id 供 refund_log 关联</li>
|
|
||||||
* </ol>
|
|
||||||
*
|
|
||||||
* <p>异常仅记录日志不向上抛,不影响主流程返回成功。
|
|
||||||
*/
|
*/
|
||||||
private Long syncAppointmentReturnStatus(Encounter encounter, String reason) {
|
private void syncAppointmentReturnStatus(Encounter encounter, String reason) {
|
||||||
if (encounter == null || encounter.getPatientId() == null) {
|
if (encounter == null || encounter.getPatientId() == null) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<Order>()
|
LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<Order>()
|
||||||
.eq(Order::getPatientId, encounter.getPatientId())
|
.eq(Order::getPatientId, encounter.getPatientId())
|
||||||
|
.in(Order::getStatus, CommonConstants.AppointmentOrderStatus.BOOKED,
|
||||||
|
CommonConstants.AppointmentOrderStatus.CHECKED_IN)
|
||||||
.orderByDesc(Order::getUpdateTime)
|
.orderByDesc(Order::getUpdateTime)
|
||||||
.orderByDesc(Order::getCreateTime)
|
.orderByDesc(Order::getCreateTime)
|
||||||
.last("LIMIT 1");
|
.last("LIMIT 1");
|
||||||
@@ -627,55 +625,35 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
|
|||||||
|
|
||||||
Order appointmentOrder = orderService.getOne(queryWrapper, false);
|
Order appointmentOrder = orderService.getOne(queryWrapper, false);
|
||||||
if (appointmentOrder == null) {
|
if (appointmentOrder == null) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只有有效订单(1)才能退号
|
Date now = new Date();
|
||||||
if (!OrderStatus.ACTIVE.getValue().equals(appointmentOrder.getStatus())) {
|
if (!CommonConstants.AppointmentOrderStatus.RETURNED.equals(appointmentOrder.getStatus())) {
|
||||||
log.warn("退号跳过:订单状态非有效, orderId={}, status={}",
|
Order updateOrder = new Order();
|
||||||
appointmentOrder.getId(), appointmentOrder.getStatus());
|
updateOrder.setId(appointmentOrder.getId());
|
||||||
return null;
|
updateOrder.setStatus(CommonConstants.AppointmentOrderStatus.RETURNED);
|
||||||
}
|
updateOrder.setPayStatus(0);
|
||||||
|
updateOrder.setCancelTime(now);
|
||||||
// 乐观锁更新:WHERE version = 旧值,防并发重复退号
|
updateOrder.setCancelReason("门诊退号");
|
||||||
boolean updated = orderService.update(
|
updateOrder.setUpdateTime(now);
|
||||||
new LambdaUpdateWrapper<Order>()
|
orderService.updateById(updateOrder);
|
||||||
.set(Order::getStatus, OrderStatus.PATIENT_CANCELLED.getValue())
|
|
||||||
.set(Order::getPayStatus, PaymentStatus.REFUND_ALL.getValue())
|
|
||||||
.set(Order::getCancelTime, new Date())
|
|
||||||
.set(Order::getCancelReason,
|
|
||||||
StringUtils.isNotEmpty(reason) ? reason : "诊前退号")
|
|
||||||
.set(Order::getUpdateTime, new Date())
|
|
||||||
.setSql("version = version + 1")
|
|
||||||
.eq(Order::getId, appointmentOrder.getId())
|
|
||||||
.eq(Order::getVersion, appointmentOrder.getVersion())
|
|
||||||
);
|
|
||||||
if (!updated) {
|
|
||||||
log.warn("退号乐观锁冲突,订单已被其他操作修改, orderId={}", appointmentOrder.getId());
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Long slotId = appointmentOrder.getSlotId();
|
Long slotId = appointmentOrder.getSlotId();
|
||||||
if (slotId == null) {
|
if (slotId == null) {
|
||||||
return appointmentOrder.getId();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int slotRows = scheduleSlotMapper.updateSlotStatus(slotId, CommonConstants.SlotStatus.AVAILABLE);
|
int slotRows = scheduleSlotMapper.updateSlotStatus(slotId, CommonConstants.SlotStatus.RETURNED);
|
||||||
if (slotRows > 0) {
|
if (slotRows > 0) {
|
||||||
Long poolId = scheduleSlotMapper.selectPoolIdBySlotId(slotId);
|
Long poolId = scheduleSlotMapper.selectPoolIdBySlotId(slotId);
|
||||||
if (poolId != null) {
|
if (poolId != null) {
|
||||||
schedulePoolMapper.refreshPoolStats(poolId);
|
schedulePoolMapper.refreshPoolStats(poolId);
|
||||||
schedulePoolMapper.update(null,
|
|
||||||
new LambdaUpdateWrapper<SchedulePool>()
|
|
||||||
.setSql("version = version + 1")
|
|
||||||
.set(SchedulePool::getUpdateTime, new Date())
|
|
||||||
.eq(SchedulePool::getId, poolId));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return appointmentOrder.getId();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("同步预约号源已退号状态失败, encounterId={}", encounter.getId(), e);
|
log.warn("同步预约号源已退号状态失败, encounterId={}", encounter.getId(), e);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,29 +672,22 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录退号日志(独立事务)。
|
* 记录退号日志
|
||||||
*
|
|
||||||
* <p>REQUIRES_NEW 确保即使主事务回滚,退号审计日志也不丢失。
|
|
||||||
* orderMainId 优先使用 order_main.id,若退费失败则 fallback 到 encounterId。
|
|
||||||
*
|
*
|
||||||
* @param cancelRegPaymentDto 退号请求对象
|
* @param cancelRegPaymentDto 退号请求对象
|
||||||
* @param encounter 就诊信息
|
* @param encounter 就诊信息
|
||||||
* @param result 退号结果
|
* @param result 退号结果
|
||||||
* @param paymentRecon 支付对账信息
|
* @param paymentRecon 支付对账信息
|
||||||
* @param orderMainId 预约订单主键(order_main.id),用于关联业务数据
|
|
||||||
*/
|
*/
|
||||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||||
public void recordRefundLog(CancelRegPaymentDto cancelRegPaymentDto,
|
public void recordRefundLog(CancelRegPaymentDto cancelRegPaymentDto,
|
||||||
Encounter encounter,
|
Encounter encounter,
|
||||||
R<?> result,
|
R<?> result,
|
||||||
PaymentReconciliation paymentRecon,
|
PaymentReconciliation paymentRecon) {
|
||||||
Long orderMainId) {
|
|
||||||
RefundLog refundLog = new RefundLog();
|
RefundLog refundLog = new RefundLog();
|
||||||
try {
|
try {
|
||||||
// 1. 订单ID(关联 order_main.id)
|
// 1. 订单ID(唯一)
|
||||||
String orderId = orderMainId != null
|
String orderId = String.valueOf(cancelRegPaymentDto.getEncounterId());
|
||||||
? String.valueOf(orderMainId)
|
|
||||||
: String.valueOf(cancelRegPaymentDto.getEncounterId());
|
|
||||||
refundLog.setOrderId(orderId);
|
refundLog.setOrderId(orderId);
|
||||||
|
|
||||||
// 已存在则不重复插入(防止唯一约束异常)
|
// 已存在则不重复插入(防止唯一约束异常)
|
||||||
|
|||||||
@@ -1991,7 +1991,7 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
|
|||||||
Order appointmentOrder = iOrderService.getOne(
|
Order appointmentOrder = iOrderService.getOne(
|
||||||
new LambdaQueryWrapper<Order>()
|
new LambdaQueryWrapper<Order>()
|
||||||
.eq(Order::getPatientId, encounterFormData.getPatientId())
|
.eq(Order::getPatientId, encounterFormData.getPatientId())
|
||||||
.eq(Order::getStatus, OrderStatus.ACTIVE.getValue()) // 有效订单(1)
|
.eq(Order::getStatus, CommonConstants.AppointmentOrderStatus.CHECKED_IN)
|
||||||
.eq(Order::getDeleteFlag, "0")
|
.eq(Order::getDeleteFlag, "0")
|
||||||
.orderByDesc(Order::getCreateTime)
|
.orderByDesc(Order::getCreateTime)
|
||||||
.last("LIMIT 1")
|
.last("LIMIT 1")
|
||||||
@@ -2114,11 +2114,11 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
|
|||||||
Long queuePoolId = null;
|
Long queuePoolId = null;
|
||||||
Long queueSlotId = null;
|
Long queueSlotId = null;
|
||||||
try {
|
try {
|
||||||
// 查询患者当天有效订单(1);已取消(0/2)和已完成(3)的不参与排队
|
// 查询患者当天的待签到预约订单(status = 1 或 2 表示已预约或已取号)
|
||||||
Order order = iOrderService.getOne(
|
Order order = iOrderService.getOne(
|
||||||
new LambdaQueryWrapper<Order>()
|
new LambdaQueryWrapper<Order>()
|
||||||
.eq(Order::getPatientId, encounter.getPatientId())
|
.eq(Order::getPatientId, encounter.getPatientId())
|
||||||
.eq(Order::getStatus, OrderStatus.ACTIVE.getValue()) // 有效(1)
|
.in(Order::getStatus, 1, 2) // 1=BOOKED 已预约, 2=CHECKED_IN 已取号
|
||||||
.eq(Order::getDeleteFlag, "0")
|
.eq(Order::getDeleteFlag, "0")
|
||||||
.orderByDesc(Order::getCreateTime)
|
.orderByDesc(Order::getCreateTime)
|
||||||
.last("LIMIT 1")
|
.last("LIMIT 1")
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright ©2023 CJB-CNIT Team. All rights reserved
|
|
||||||
*/
|
|
||||||
package com.openhis.common.enums;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单状态 (order_main.status)
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* 状态流转:
|
|
||||||
* 创建订单 → ACTIVE(1)
|
|
||||||
* 签到 → ACTIVE(1) 不变
|
|
||||||
* 患者退号 → PATIENT_CANCELLED(0)
|
|
||||||
* 系统取消 → SYSTEM_CANCELLED(2)
|
|
||||||
* 就诊完成 → COMPLETED(3)
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
* @author wangjian963
|
|
||||||
* @date 2026-05-09
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@AllArgsConstructor
|
|
||||||
public enum OrderStatus implements HisEnumInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 患者取消
|
|
||||||
*/
|
|
||||||
PATIENT_CANCELLED(0, "0", "患者取消"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 有效
|
|
||||||
*/
|
|
||||||
ACTIVE(1, "1", "有效"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 系统取消
|
|
||||||
*/
|
|
||||||
SYSTEM_CANCELLED(2, "2", "系统取消"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 已完成
|
|
||||||
*/
|
|
||||||
COMPLETED(3, "3", "已完成");
|
|
||||||
|
|
||||||
private Integer value;
|
|
||||||
private String code;
|
|
||||||
private String info;
|
|
||||||
|
|
||||||
public static OrderStatus getByValue(Integer value) {
|
|
||||||
if (value == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (OrderStatus val : values()) {
|
|
||||||
if (val.getValue().equals(value)) {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,8 +6,8 @@ import com.core.common.utils.AssignSeqUtil;
|
|||||||
import com.openhis.clinical.domain.Order;
|
import com.openhis.clinical.domain.Order;
|
||||||
import com.openhis.clinical.mapper.OrderMapper;
|
import com.openhis.clinical.mapper.OrderMapper;
|
||||||
import com.openhis.clinical.service.IOrderService;
|
import com.openhis.clinical.service.IOrderService;
|
||||||
|
import com.openhis.common.constant.CommonConstants.AppointmentOrderStatus;
|
||||||
import com.openhis.common.enums.AssignSeqEnum;
|
import com.openhis.common.enums.AssignSeqEnum;
|
||||||
import com.openhis.common.enums.OrderStatus;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
@@ -124,8 +124,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
: new Date(); // 兜底:正常业务不应走到这里
|
: new Date(); // 兜底:正常业务不应走到这里
|
||||||
order.setAppointmentDate(appointmentDateTime);
|
order.setAppointmentDate(appointmentDateTime);
|
||||||
order.setAppointmentTime(appointmentDateTime);
|
order.setAppointmentTime(appointmentDateTime);
|
||||||
// 订单状态: 0=患者取消 1=有效 2=系统取消 3=已完成
|
order.setStatus(AppointmentOrderStatus.BOOKED);
|
||||||
order.setStatus(OrderStatus.ACTIVE.getValue());
|
|
||||||
order.setPayStatus(0);
|
order.setPayStatus(0);
|
||||||
order.setVersion(0);
|
order.setVersion(0);
|
||||||
|
|
||||||
@@ -170,13 +169,10 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
if (order == null) {
|
if (order == null) {
|
||||||
throw new RuntimeException("订单不存在");
|
throw new RuntimeException("订单不存在");
|
||||||
}
|
}
|
||||||
// 已取消(患者取消0 或 系统取消2)不可再次取消
|
if (AppointmentOrderStatus.CANCELLED.equals(order.getStatus())) {
|
||||||
if (OrderStatus.PATIENT_CANCELLED.getValue().equals(order.getStatus())
|
|
||||||
|| OrderStatus.SYSTEM_CANCELLED.getValue().equals(order.getStatus())) {
|
|
||||||
throw new RuntimeException("订单已取消");
|
throw new RuntimeException("订单已取消");
|
||||||
}
|
}
|
||||||
// 已完成(3)的订单不可取消
|
if (AppointmentOrderStatus.CHECKED_IN.equals(order.getStatus())) {
|
||||||
if (OrderStatus.COMPLETED.getValue().equals(order.getStatus())) {
|
|
||||||
throw new RuntimeException("订单已完成,无法取消");
|
throw new RuntimeException("订单已完成,无法取消");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +189,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
.eq(Order::getPatientId, patientId)
|
.eq(Order::getPatientId, patientId)
|
||||||
.eq(Order::getTenantId, tenantId)
|
.eq(Order::getTenantId, tenantId)
|
||||||
.ge(Order::getCancelTime, startTime)
|
.ge(Order::getCancelTime, startTime)
|
||||||
// 只统计患者主动取消(0),不含系统取消(2)
|
.eq(Order::getStatus, AppointmentOrderStatus.CANCELLED));
|
||||||
.eq(Order::getStatus, OrderStatus.PATIENT_CANCELLED.getValue()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import com.openhis.clinical.domain.Ticket;
|
|||||||
import com.openhis.clinical.mapper.TicketMapper;
|
import com.openhis.clinical.mapper.TicketMapper;
|
||||||
import com.openhis.clinical.service.IOrderService;
|
import com.openhis.clinical.service.IOrderService;
|
||||||
import com.openhis.clinical.service.ITicketService;
|
import com.openhis.clinical.service.ITicketService;
|
||||||
|
import com.openhis.common.constant.CommonConstants.AppointmentOrderStatus;
|
||||||
import com.openhis.common.constant.CommonConstants.SlotStatus;
|
import com.openhis.common.constant.CommonConstants.SlotStatus;
|
||||||
import com.openhis.common.enums.OrderStatus;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -195,8 +195,8 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
|
|||||||
Date startTime = Date.from(periodStart.atZone(ZoneId.systemDefault()).toInstant());
|
Date startTime = Date.from(periodStart.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
Date endTime = Date.from(periodEnd.atZone(ZoneId.systemDefault()).toInstant());
|
Date endTime = Date.from(periodEnd.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
|
||||||
// 预约去重以订单为准(order_main),有效订单(1)才参与去重
|
// 预约去重以订单为准(order_main),因为预约成功会先落订单;clinical_ticket 不一定在此链路写入
|
||||||
List<Integer> effectiveOrderStatuses = Arrays.asList(OrderStatus.ACTIVE.getValue());
|
List<Integer> effectiveOrderStatuses = Arrays.asList(AppointmentOrderStatus.BOOKED, AppointmentOrderStatus.CHECKED_IN);
|
||||||
int exists = orderMapper.countPatientDeptOrdersInPeriod(dto.getPatientId(), slot.getDepartmentId(), slot.getDepartmentName(),
|
int exists = orderMapper.countPatientDeptOrdersInPeriod(dto.getPatientId(), slot.getDepartmentId(), slot.getDepartmentName(),
|
||||||
startTime, endTime, effectiveOrderStatuses);
|
startTime, endTime, effectiveOrderStatuses);
|
||||||
if (exists > 0) {
|
if (exists > 0) {
|
||||||
@@ -314,8 +314,9 @@ public class TicketServiceImpl extends ServiceImpl<TicketMapper, Ticket> impleme
|
|||||||
}
|
}
|
||||||
Order latestOrder = orders.get(0);
|
Order latestOrder = orders.get(0);
|
||||||
|
|
||||||
// 1. 签到不改变订单状态(仍为有效1),更新支付状态为已支付并记录支付时间
|
// 1. 更新订单状态为已取号,并更新支付状态和支付时间
|
||||||
orderService.updateOrderStatusById(latestOrder.getId(), OrderStatus.ACTIVE.getValue());
|
orderService.updateOrderStatusById(latestOrder.getId(), AppointmentOrderStatus.CHECKED_IN);
|
||||||
|
// 更新支付状态为已支付,记录支付时间
|
||||||
orderMapper.updatePayStatus(latestOrder.getId(), 1, new Date());
|
orderMapper.updatePayStatus(latestOrder.getId(), 1, new Date());
|
||||||
|
|
||||||
// 2. 查询号源槽位信息
|
// 2. 查询号源槽位信息
|
||||||
|
|||||||
@@ -160,12 +160,11 @@
|
|||||||
AND delete_flag = '0'
|
AND delete_flag = '0'
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<!-- status=0(待约)时清空order_id,释放号源,使退号后号源可再被预约 -->
|
|
||||||
<update id="updateSlotStatus">
|
<update id="updateSlotStatus">
|
||||||
UPDATE adm_schedule_slot
|
UPDATE adm_schedule_slot
|
||||||
SET
|
SET
|
||||||
status = #{status},
|
status = #{status},
|
||||||
<if test="status != null and status == 0">
|
<if test="status != null and '0'.equals(status.toString())">
|
||||||
order_id = NULL,
|
order_id = NULL,
|
||||||
</if>
|
</if>
|
||||||
update_time = now()
|
update_time = now()
|
||||||
|
|||||||
@@ -117,14 +117,12 @@
|
|||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- status=1: 只查有效订单(0=患者取消 1=有效 2=系统取消 3=已完成) -->
|
|
||||||
<select id="selectOrderById" resultMap="OrderResult">
|
<select id="selectOrderById" resultMap="OrderResult">
|
||||||
select * from order_main where id = #{id}
|
select * from order_main where id = #{id}
|
||||||
and status = 1
|
and status = 1
|
||||||
order by create_time desc
|
order by create_time desc
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<!-- status=1: 只查有效订单 -->
|
|
||||||
<select id="selectOrderBySlotId" resultMap="OrderResult">
|
<select id="selectOrderBySlotId" resultMap="OrderResult">
|
||||||
select * from order_main where slot_id = #{slotId} and status = 1
|
select * from order_main where slot_id = #{slotId} and status = 1
|
||||||
</select>
|
</select>
|
||||||
@@ -250,9 +248,8 @@
|
|||||||
update order_main set status = #{status} where id = #{id}
|
update order_main set status = #{status} where id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<!-- status=0: 患者取消 (OrderStatus.PATIENT_CANCELLED) -->
|
|
||||||
<update id="updateOrderCancelInfoById">
|
<update id="updateOrderCancelInfoById">
|
||||||
update order_main set status = 0, cancel_time = #{cancelTime}, cancel_reason = #{cancelReason} where id = #{id}
|
update order_main set status = 3, cancel_time = #{cancelTime}, cancel_reason = #{cancelReason} where id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
<update id="updatePayStatus">
|
<update id="updatePayStatus">
|
||||||
|
|||||||
@@ -2063,15 +2063,20 @@ watch(() => props.patientInfo, async (newVal) => {
|
|||||||
}
|
}
|
||||||
}, { deep: true, immediate: true })
|
}, { deep: true, immediate: true })
|
||||||
|
|
||||||
// Bug #329: 监听已选择的检验项目,自动更新检验项目文本并设置默认执行科室
|
// Bug #329/#466: 监听已选择的检验项目,自动更新检验项目文本并设置默认执行科室、标本类型
|
||||||
watch(() => selectedInspectionItems.value, async (newVal) => {
|
watch(() => selectedInspectionItems.value, async (newVal) => {
|
||||||
if (newVal && newVal.length > 0) {
|
if (newVal && newVal.length > 0) {
|
||||||
formData.inspectionItemsText = newVal.map(item => item.itemName).join('+')
|
formData.inspectionItemsText = newVal.map(item => item.itemName).join('+')
|
||||||
|
|
||||||
|
const firstItem = newVal[0]
|
||||||
|
|
||||||
|
// Bug #466: 如果标本类型为空或仍为初始化默认值,根据第一个检验项目的 sampleType 自动设置默认标本类型
|
||||||
|
if ((!formData.specimenName || formData.specimenName === '血液') && firstItem.sampleType) {
|
||||||
|
formData.specimenName = firstItem.sampleType
|
||||||
|
}
|
||||||
|
|
||||||
// Bug #329: 如果执行科室为空,根据第一个检验项目的检验类型自动设置默认执行科室
|
// Bug #329: 如果执行科室为空,根据第一个检验项目的检验类型自动设置默认执行科室
|
||||||
if (!formData.executeDepartment) {
|
if (!formData.executeDepartment) {
|
||||||
const firstItem = newVal[0]
|
|
||||||
|
|
||||||
// 根据检验项目的 inspectionTypeId 获取默认执行科室
|
// 根据检验项目的 inspectionTypeId 获取默认执行科室
|
||||||
if (firstItem.inspectionTypeId) {
|
if (firstItem.inspectionTypeId) {
|
||||||
const defaultDeptCode = await getDefaultPerformDeptCode(firstItem.inspectionTypeId)
|
const defaultDeptCode = await getDefaultPerformDeptCode(firstItem.inspectionTypeId)
|
||||||
@@ -2081,9 +2086,10 @@ watch(() => selectedInspectionItems.value, async (newVal) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Bug #329: 当项目被清空时,同时清空执行科室(下次选择项目时会重新自动设置)
|
// Bug #329: 当项目被清空时,同时清空执行科室和标本类型(下次选择项目时会重新自动设置)
|
||||||
formData.inspectionItemsText = ''
|
formData.inspectionItemsText = ''
|
||||||
formData.executeDepartment = ''
|
formData.executeDepartment = ''
|
||||||
|
formData.specimenName = ''
|
||||||
}
|
}
|
||||||
}, { deep: true })
|
}, { deep: true })
|
||||||
|
|
||||||
|
|||||||
@@ -86,14 +86,14 @@ const tableColumns = computed<TableColumn[]>(() => [
|
|||||||
* @param searchKey 搜索关键词
|
* @param searchKey 搜索关键词
|
||||||
*/
|
*/
|
||||||
function refresh(adviceType: any, categoryCode: string, searchKey: string) {
|
function refresh(adviceType: any, categoryCode: string, searchKey: string) {
|
||||||
// 有搜索词时跨类型搜索,避免用户输入"级护理"但因当前adviceType为药品而搜不到诊疗类护理项目
|
// 有搜索词时跨类型搜索,或adviceType为空时也跨类型搜索(新行未选类型时默认搜全部),避免用户输入"级护理"但因当前adviceType为药品而搜不到诊疗类护理项目
|
||||||
if (searchKey) {
|
if (searchKey || adviceType === undefined || adviceType === '') {
|
||||||
queryParams.value.adviceTypes = '1,2,3,6';
|
queryParams.value.adviceTypes = '1,2,3,6';
|
||||||
|
queryParams.value.categoryCode = '';
|
||||||
} else {
|
} else {
|
||||||
queryParams.value.adviceTypes =
|
queryParams.value.adviceTypes = String(adviceType);
|
||||||
adviceType !== undefined && adviceType !== '' ? String(adviceType) : '1,2,3,6';
|
queryParams.value.categoryCode = categoryCode || '';
|
||||||
}
|
}
|
||||||
queryParams.value.categoryCode = categoryCode || '';
|
|
||||||
queryParams.value.searchKey = searchKey || '';
|
queryParams.value.searchKey = searchKey || '';
|
||||||
getList();
|
getList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,13 +281,14 @@ const submit = () => {
|
|||||||
accountId: patientInfo.value.accountId, // // 账户id
|
accountId: patientInfo.value.accountId, // // 账户id
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
const itemNames = applicationListAllFilter.map(item => item.adviceName).filter(Boolean).join('、');
|
||||||
saveCheckd({
|
saveCheckd({
|
||||||
activityList: applicationListAllFilter,
|
activityList: applicationListAllFilter,
|
||||||
patientId: patientInfo.value.patientId, //患者ID
|
patientId: patientInfo.value.patientId, //患者ID
|
||||||
encounterId: patientInfo.value.encounterId, // 就诊ID
|
encounterId: patientInfo.value.encounterId, // 就诊ID
|
||||||
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
|
organizationId: patientInfo.value.inHospitalOrgId, // 医疗机构ID
|
||||||
requestFormId: '', // 申请单ID
|
requestFormId: '', // 申请单ID
|
||||||
name: '检查申请单',
|
name: itemNames || '检查申请单',
|
||||||
descJson: JSON.stringify(form),
|
descJson: JSON.stringify(form),
|
||||||
categoryEnum: '2', // 1 检验 2 检查 3 输血 4 手术
|
categoryEnum: '2', // 1 检验 2 检查 3 输血 4 手术
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
|
|||||||
@@ -802,10 +802,8 @@ function clickRowDb(row, column, event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
row.showPopover = false;
|
row.showPopover = false;
|
||||||
// 允许所有 statusEnum==1 的医嘱进入编辑:
|
// “待签发(已保存 requestId存在)”不允许再编辑;仅“待保存(无requestId)”允许编辑
|
||||||
// 1. 新医嘱(无 requestId):待保存
|
if (row.statusEnum == 1 && !row.requestId) {
|
||||||
// 2. 护士退回医嘱(有 requestId):退回后状态重置为 DRAFT(1),需允许医生编辑修改后重新签发
|
|
||||||
if (row.statusEnum == 1) {
|
|
||||||
// 确保治疗类型为字符串,方便与单选框 label 对齐,默认为长期医嘱('1')
|
// 确保治疗类型为字符串,方便与单选框 label 对齐,默认为长期医嘱('1')
|
||||||
row.therapyEnum = String(row.therapyEnum ?? '1');
|
row.therapyEnum = String(row.therapyEnum ?? '1');
|
||||||
row.isEdit = true;
|
row.isEdit = true;
|
||||||
|
|||||||
@@ -1481,6 +1481,8 @@ function handleMedicalAdvice(row) {
|
|||||||
const filteredItems = res.data.filter(item => {
|
const filteredItems = res.data.filter(item => {
|
||||||
// 匹配 encounterId
|
// 匹配 encounterId
|
||||||
if (item.encounterId !== row.visitId) return false;
|
if (item.encounterId !== row.visitId) return false;
|
||||||
|
// 仅保留药品(adviceType=1),过滤耗材(2)和项目(3)
|
||||||
|
if (item.adviceType !== 1 && item.advice_type !== 1) return false;
|
||||||
// 过滤掉名称为空的项目
|
// 过滤掉名称为空的项目
|
||||||
const medicineName = item.adviceName || item.advice_name;
|
const medicineName = item.adviceName || item.advice_name;
|
||||||
if (!medicineName || medicineName.trim() === '') return false;
|
if (!medicineName || medicineName.trim() === '') return false;
|
||||||
@@ -1743,6 +1745,8 @@ function handleQuoteBilling() {
|
|||||||
const filteredItems = res.data.filter(item => {
|
const filteredItems = res.data.filter(item => {
|
||||||
// 匹配 encounterId
|
// 匹配 encounterId
|
||||||
if (item.encounterId !== temporaryPatientInfo.value.visitId) return false;
|
if (item.encounterId !== temporaryPatientInfo.value.visitId) return false;
|
||||||
|
// 仅保留药品(adviceType=1),过滤耗材(2)和项目(3)
|
||||||
|
if (item.adviceType !== 1 && item.advice_type !== 1) return false;
|
||||||
// 过滤掉名称为空的项目
|
// 过滤掉名称为空的项目
|
||||||
const medicineName = item.adviceName || item.advice_name;
|
const medicineName = item.adviceName || item.advice_name;
|
||||||
return medicineName && medicineName.trim() !== '';
|
return medicineName && medicineName.trim() !== '';
|
||||||
|
|||||||
@@ -198,52 +198,53 @@
|
|||||||
↓
|
↓
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="queue-actions-right">
|
||||||
|
<el-button
|
||||||
|
:type="showOnlyWaiting ? 'primary' : ''"
|
||||||
|
size="small"
|
||||||
|
@click="showOnlyWaiting = true"
|
||||||
|
>
|
||||||
|
只显示等待
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
:type="!showOnlyWaiting ? 'primary' : ''"
|
||||||
|
size="small"
|
||||||
|
@click="showOnlyWaiting = false"
|
||||||
|
>
|
||||||
|
显示全部状态
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 底部控制面板 -->
|
<!-- 底部控制面板 -->
|
||||||
<div class="footer-section">
|
<div class="footer-section">
|
||||||
<!-- Bug #411:诊室快速过滤栏,筛选维度从科室改为诊室 -->
|
<!-- 诊室快速过滤栏 -->
|
||||||
<div class="filter-section">
|
<div class="filter-section">
|
||||||
<div class="filter-left">
|
<div class="filter-label">
|
||||||
<div class="filter-label">
|
③ 诊室快速过滤栏
|
||||||
③ 诊室快速过滤栏
|
|
||||||
</div>
|
|
||||||
<div class="filter-button-wrapper">
|
|
||||||
<el-button
|
|
||||||
:type="selectedRoom === 'all' ? 'primary' : ''"
|
|
||||||
size="small"
|
|
||||||
@click="selectedRoom = 'all'"
|
|
||||||
>
|
|
||||||
全部
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-for="room in uniqueRooms"
|
|
||||||
:key="room"
|
|
||||||
:type="selectedRoom === room ? 'primary' : ''"
|
|
||||||
size="small"
|
|
||||||
@click="selectedRoom = room"
|
|
||||||
>
|
|
||||||
{{ room }}
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-right">
|
<div class="filter-select-wrapper">
|
||||||
<el-button
|
<el-select
|
||||||
:type="showOnlyWaiting ? 'primary' : ''"
|
v-model="selectedClinicRoom"
|
||||||
size="small"
|
placeholder="请选择诊室"
|
||||||
@click="showOnlyWaiting = true"
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 100%"
|
||||||
|
size="default"
|
||||||
>
|
>
|
||||||
只显示等待
|
<el-option
|
||||||
</el-button>
|
label="全部"
|
||||||
<el-button
|
value="all"
|
||||||
:type="!showOnlyWaiting ? 'primary' : ''"
|
/>
|
||||||
size="small"
|
<el-option
|
||||||
@click="showOnlyWaiting = false"
|
v-for="room in clinicRoomList"
|
||||||
>
|
:key="room"
|
||||||
显示全部状态
|
:label="room"
|
||||||
</el-button>
|
:value="room"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -679,8 +680,10 @@ const selectedCandidates = ref([])
|
|||||||
// 显示选项
|
// 显示选项
|
||||||
const showOnlyWaiting = ref(false)
|
const showOnlyWaiting = ref(false)
|
||||||
|
|
||||||
// Bug #411:诊室过滤,替代原来的科室下拉框(selectedDept/departmentList 已移除)
|
// 诊室过滤(按诊室维度筛选)
|
||||||
const selectedRoom = ref('all')
|
const selectedClinicRoom = ref('all')
|
||||||
|
// 诊室列表(从数据中动态提取)
|
||||||
|
const clinicRoomList = ref([])
|
||||||
|
|
||||||
// 修复【#397】:动态获取当前科室名称
|
// 修复【#397】:动态获取当前科室名称
|
||||||
const currentDeptName = computed(() => {
|
const currentDeptName = computed(() => {
|
||||||
@@ -903,12 +906,11 @@ const mapFrontendStatusToBackend = (status) => {
|
|||||||
// 从数据库加载队列
|
// 从数据库加载队列
|
||||||
const loadQueueFromDb = async () => {
|
const loadQueueFromDb = async () => {
|
||||||
try {
|
try {
|
||||||
// Bug #411:不再按科室选筛加载,后端默认按当前登录人科室查询
|
// 使用当前登录人的科室
|
||||||
const organizationId = undefined
|
|
||||||
// 只查询今天的患者
|
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`
|
const todayStr = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}-${String(today.getDate()).padStart(2, '0')}`
|
||||||
const res = await getTriageQueueList({ organizationId, date: todayStr }).catch((err) => {
|
console.log('【心内科】loadQueueFromDb 开始:date=', todayStr)
|
||||||
|
const res = await getTriageQueueList({ date: todayStr }).catch((err) => {
|
||||||
console.error('【心内科】loadQueueFromDb 请求异常:', err)
|
console.error('【心内科】loadQueueFromDb 请求异常:', err)
|
||||||
return { code: 500, msg: err?.message || '请求失败', data: null }
|
return { code: 500, msg: err?.message || '请求失败', data: null }
|
||||||
})
|
})
|
||||||
@@ -1136,6 +1138,8 @@ const loadDataFromApi = async () => {
|
|||||||
|
|
||||||
// 同步当前呼叫(队列从 DB 加载后已同步;这里再兜底一次)
|
// 同步当前呼叫(队列从 DB 加载后已同步;这里再兜底一次)
|
||||||
syncCurrentCallFromQueue()
|
syncCurrentCallFromQueue()
|
||||||
|
// 提取诊室列表供过滤栏使用
|
||||||
|
extractClinicRooms()
|
||||||
console.log('【心内科】数据加载完成:候选池', originalCandidatePoolList.value.length, '条,队列', originalQueueList.value.length, '条')
|
console.log('【心内科】数据加载完成:候选池', originalCandidatePoolList.value.length, '条,队列', originalQueueList.value.length, '条')
|
||||||
ElMessage.success('【心内科】已从门诊挂号接口加载数据')
|
ElMessage.success('【心内科】已从门诊挂号接口加载数据')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1147,35 +1151,42 @@ const loadDataFromApi = async () => {
|
|||||||
totalSignedIn.value = originalCandidatePoolList.value.length
|
totalSignedIn.value = originalCandidatePoolList.value.length
|
||||||
totalInQueue.value = originalQueueList.value.length
|
totalInQueue.value = originalQueueList.value.length
|
||||||
syncCurrentCallFromQueue()
|
syncCurrentCallFromQueue()
|
||||||
|
extractClinicRooms()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 原始数据存储(用于过滤)
|
// 原始数据存储(用于过滤)
|
||||||
const originalCandidatePoolList = ref(getInitialCandidatePoolList())
|
const originalCandidatePoolList = ref(getInitialCandidatePoolList())
|
||||||
|
|
||||||
// 过滤后的智能候选池数据(按诊室过滤)
|
// 提取诊室列表(从队列和候选池数据中动态获取)
|
||||||
|
const extractClinicRooms = () => {
|
||||||
|
const roomSet = new Set()
|
||||||
|
// 从队列中提取
|
||||||
|
originalQueueList.value.forEach(item => {
|
||||||
|
if (item.room && item.room !== '-') {
|
||||||
|
roomSet.add(item.room)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 从候选池中提取
|
||||||
|
originalCandidatePoolList.value.forEach(item => {
|
||||||
|
if (item.room && item.room !== '-') {
|
||||||
|
roomSet.add(item.room)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
clinicRoomList.value = Array.from(roomSet).sort()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤后的智能候选池数据
|
||||||
const filteredCandidatePoolList = computed(() => {
|
const filteredCandidatePoolList = computed(() => {
|
||||||
if (selectedRoom.value === 'all') {
|
if (selectedClinicRoom.value === 'all') {
|
||||||
return originalCandidatePoolList.value
|
return originalCandidatePoolList.value
|
||||||
}
|
}
|
||||||
return originalCandidatePoolList.value.filter(item => item.room === selectedRoom.value)
|
return originalCandidatePoolList.value.filter(item => item.room === selectedClinicRoom.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 原始队列数据存储(用于过滤)
|
// 原始队列数据存储(用于过滤)
|
||||||
const originalQueueList = ref(getInitialQueueList())
|
const originalQueueList = ref(getInitialQueueList())
|
||||||
|
|
||||||
// 动态计算已加载数据中的唯一诊室列表(依赖上方两个 ref,确保声明顺序正确)
|
|
||||||
const uniqueRooms = computed(() => {
|
|
||||||
const rooms = new Set()
|
|
||||||
originalCandidatePoolList.value.forEach(item => {
|
|
||||||
if (item.room && item.room !== '-') rooms.add(item.room)
|
|
||||||
})
|
|
||||||
originalQueueList.value.forEach(item => {
|
|
||||||
if (item.room && item.room !== '-') rooms.add(item.room)
|
|
||||||
})
|
|
||||||
return Array.from(rooms).sort()
|
|
||||||
})
|
|
||||||
|
|
||||||
const parseMmSsToSeconds = (mmss) => {
|
const parseMmSsToSeconds = (mmss) => {
|
||||||
if (!mmss || typeof mmss !== 'string') return 0
|
if (!mmss || typeof mmss !== 'string') return 0
|
||||||
const [mm, ss] = mmss.split(':')
|
const [mm, ss] = mmss.split(':')
|
||||||
@@ -1192,7 +1203,7 @@ const formatSecondsToMmSs = (totalSeconds) => {
|
|||||||
return `${mm}:${ss}`
|
return `${mm}:${ss}`
|
||||||
}
|
}
|
||||||
|
|
||||||
// 过滤后的智能队列数据(Bug #411:诊室过滤 + 状态过滤)
|
// 过滤后的智能队列数据(同时考虑诊室过滤和状态过滤)
|
||||||
const filteredQueueList = computed(() => {
|
const filteredQueueList = computed(() => {
|
||||||
let filtered = originalQueueList.value
|
let filtered = originalQueueList.value
|
||||||
|
|
||||||
@@ -1200,8 +1211,8 @@ const filteredQueueList = computed(() => {
|
|||||||
filtered = filtered.filter(item => item.status !== '已完成')
|
filtered = filtered.filter(item => item.status !== '已完成')
|
||||||
|
|
||||||
// 再按诊室过滤
|
// 再按诊室过滤
|
||||||
if (selectedRoom.value !== 'all') {
|
if (selectedClinicRoom.value !== 'all') {
|
||||||
filtered = filtered.filter(item => item.room === selectedRoom.value)
|
filtered = filtered.filter(item => item.room === selectedClinicRoom.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 再按状态过滤(只显示等待)
|
// 再按状态过滤(只显示等待)
|
||||||
@@ -1712,12 +1723,16 @@ const handleNextPatient = async () => {
|
|||||||
reqData.id = selectedQueueRow.value.id
|
reqData.id = selectedQueueRow.value.id
|
||||||
reqData.organizationId = selectedQueueRow.value.organizationId
|
reqData.organizationId = selectedQueueRow.value.organizationId
|
||||||
} else {
|
} else {
|
||||||
// Bug #411:已移除 selectedDept,改为从队列数据中动态获取科室
|
// 如果没有选中患者,使用查询条件(兼容旧逻辑)
|
||||||
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
// 全科模式:优先用"当前叫号中/第一个等待"所在科室
|
||||||
const waiting = originalQueueList.value.find((i) => i.status === '等待')
|
let orgId = null
|
||||||
console.log('【心内科】handleNextPatient 查找:叫号中=', calling?.patientName, '等待=', waiting?.patientName)
|
{
|
||||||
const orgId = calling?.organizationId ?? waiting?.organizationId
|
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
||||||
console.log('【心内科】handleNextPatient 确定的 orgId=', orgId)
|
const waiting = originalQueueList.value.find((i) => i.status === '等待')
|
||||||
|
console.log('【心内科】handleNextPatient 查找:叫号中=', calling?.patientName, '等待=', waiting?.patientName)
|
||||||
|
orgId = calling?.organizationId ?? waiting?.organizationId
|
||||||
|
console.log('【心内科】handleNextPatient 确定的 orgId=', orgId)
|
||||||
|
}
|
||||||
if (orgId != null) {
|
if (orgId != null) {
|
||||||
reqData.organizationId = orgId
|
reqData.organizationId = orgId
|
||||||
}
|
}
|
||||||
@@ -1746,9 +1761,13 @@ const handleSkip = async () => {
|
|||||||
reqData.id = selectedQueueRow.value.id
|
reqData.id = selectedQueueRow.value.id
|
||||||
reqData.organizationId = selectedQueueRow.value.organizationId
|
reqData.organizationId = selectedQueueRow.value.organizationId
|
||||||
} else {
|
} else {
|
||||||
// 如果没有选中患者,使用当前叫号中的科室
|
// 如果没有选中患者,使用查询条件(兼容旧逻辑)
|
||||||
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
// 全科模式:优先用”当前叫号中”所在科室
|
||||||
const orgId = calling?.organizationId
|
let orgId = null
|
||||||
|
{
|
||||||
|
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
||||||
|
orgId = calling?.organizationId
|
||||||
|
}
|
||||||
if (orgId != null) {
|
if (orgId != null) {
|
||||||
reqData.organizationId = orgId
|
reqData.organizationId = orgId
|
||||||
}
|
}
|
||||||
@@ -1776,9 +1795,13 @@ const handleComplete = async () => {
|
|||||||
reqData.id = selectedQueueRow.value.id
|
reqData.id = selectedQueueRow.value.id
|
||||||
reqData.organizationId = selectedQueueRow.value.organizationId
|
reqData.organizationId = selectedQueueRow.value.organizationId
|
||||||
} else {
|
} else {
|
||||||
// 如果没有选中患者,使用当前叫号中的科室
|
// 如果没有选中患者,使用查询条件(兼容旧逻辑)
|
||||||
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
// 全科模式:优先用”当前叫号中”所在科室
|
||||||
const orgId = calling?.organizationId
|
let orgId = null
|
||||||
|
{
|
||||||
|
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
||||||
|
orgId = calling?.organizationId
|
||||||
|
}
|
||||||
if (orgId != null) {
|
if (orgId != null) {
|
||||||
reqData.organizationId = orgId
|
reqData.organizationId = orgId
|
||||||
}
|
}
|
||||||
@@ -1806,9 +1829,13 @@ const handleRequeue = async () => {
|
|||||||
reqData.id = selectedQueueRow.value.id
|
reqData.id = selectedQueueRow.value.id
|
||||||
reqData.organizationId = selectedQueueRow.value.organizationId
|
reqData.organizationId = selectedQueueRow.value.organizationId
|
||||||
} else {
|
} else {
|
||||||
// 如果没有选中患者,使用当前叫号中的科室
|
// 如果没有选中患者,使用查询条件(兼容旧逻辑)
|
||||||
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
// 全科模式:优先用”当前叫号中”所在科室
|
||||||
const orgId = calling?.organizationId
|
let orgId = null
|
||||||
|
{
|
||||||
|
const calling = originalQueueList.value.find((i) => i.status === '叫号中')
|
||||||
|
orgId = calling?.organizationId
|
||||||
|
}
|
||||||
if (orgId != null) {
|
if (orgId != null) {
|
||||||
reqData.organizationId = orgId
|
reqData.organizationId = orgId
|
||||||
}
|
}
|
||||||
@@ -2192,6 +2219,10 @@ onUnmounted(() => {
|
|||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.queue-actions-right {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.candidate-actions {
|
.candidate-actions {
|
||||||
@@ -2213,32 +2244,16 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
.filter-section {
|
.filter-section {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.filter-left {
|
.filter-label {
|
||||||
flex: 1;
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
.filter-label {
|
color: #333;
|
||||||
font-size: 14px;
|
margin-bottom: 10px;
|
||||||
font-weight: bold;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter-button-wrapper {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter-right {
|
.filter-select-wrapper {
|
||||||
display: flex;
|
width: 100%;
|
||||||
gap: 8px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
align-self: flex-end;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user