Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3049bd1d7 | ||
|
|
4b0c3a6016 | ||
|
|
8951f1b0b2 | ||
|
|
28f313bd90 | ||
|
|
030b011e44 | ||
|
|
d529590978 | ||
|
|
2c560ab8b3 | ||
|
|
d7bcb2f171 | ||
|
|
2d60e3991e |
@@ -2,13 +2,9 @@ package com.openhis.web.clinicalmanage.controller;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.core.common.core.domain.R;
|
import com.core.common.core.domain.R;
|
||||||
import com.openhis.common.enums.ActivityDefCategory;
|
|
||||||
import com.openhis.web.clinicalmanage.appservice.ISurgicalScheduleAppService;
|
import com.openhis.web.clinicalmanage.appservice.ISurgicalScheduleAppService;
|
||||||
import com.openhis.web.clinicalmanage.dto.OpCreateScheduleDto;
|
import com.openhis.web.clinicalmanage.dto.OpCreateScheduleDto;
|
||||||
import com.openhis.web.clinicalmanage.dto.OpScheduleDto;
|
import com.openhis.web.clinicalmanage.dto.OpScheduleDto;
|
||||||
import com.openhis.web.regdoctorstation.appservice.IRequestFormManageAppService;
|
|
||||||
import com.openhis.web.regdoctorstation.dto.RequestFormDto;
|
|
||||||
import com.openhis.web.regdoctorstation.dto.RequestFormPageDto;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -30,7 +26,6 @@ import java.util.Map;
|
|||||||
public class SurgicalScheduleController {
|
public class SurgicalScheduleController {
|
||||||
|
|
||||||
private final ISurgicalScheduleAppService surgicalScheduleAppService;
|
private final ISurgicalScheduleAppService surgicalScheduleAppService;
|
||||||
private final IRequestFormManageAppService requestFormManageAppService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询手术安排列表
|
* 分页查询手术安排列表
|
||||||
@@ -92,27 +87,6 @@ public class SurgicalScheduleController {
|
|||||||
return surgicalScheduleAppService.deleteSurgerySchedule(scheduleId);
|
return surgicalScheduleAppService.deleteSurgerySchedule(scheduleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页查询待排期手术申请列表
|
|
||||||
*
|
|
||||||
* @param requestFormDto 查询条件
|
|
||||||
* @return 手术申请列表
|
|
||||||
*/
|
|
||||||
@PostMapping(value = "/apply-list")
|
|
||||||
public R<IPage<RequestFormPageDto>> getSurgeryApplyList(@RequestBody RequestFormDto requestFormDto) {
|
|
||||||
if (requestFormDto.getPageNo() == null) {
|
|
||||||
requestFormDto.setPageNo(1);
|
|
||||||
}
|
|
||||||
if (requestFormDto.getPageSize() == null) {
|
|
||||||
requestFormDto.setPageSize(10);
|
|
||||||
}
|
|
||||||
//虽然很想这么写,但是库里的手术申请单的type_code都是直接写的SURGERY
|
|
||||||
// requestFormDto.setTypeCode(ActivityDefCategory.PROCEDURE.getCode());
|
|
||||||
//只查询手术申请单
|
|
||||||
requestFormDto.setTypeCode("SURGERY");
|
|
||||||
return R.ok(requestFormManageAppService.getRequestFormPage(requestFormDto));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出手术安排列表
|
* 导出手术安排列表
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -59,16 +59,6 @@ public interface IDoctorStationAdviceAppService {
|
|||||||
*/
|
*/
|
||||||
R<?> getRequestBaseInfo(Long encounterId);
|
R<?> getRequestBaseInfo(Long encounterId);
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询医嘱请求数据(支持按生成来源和来源单据号过滤)
|
|
||||||
*
|
|
||||||
* @param encounterId 就诊id
|
|
||||||
* @param generateSourceEnum 生成来源(可选,如手术计费=6)
|
|
||||||
* @param sourceBillNo 来源业务单据号(可选)
|
|
||||||
* @return 医嘱请求数据
|
|
||||||
*/
|
|
||||||
R<?> getRequestBaseInfo(Long encounterId, Integer generateSourceEnum, String sourceBillNo);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 门诊签退医嘱
|
* 门诊签退医嘱
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -228,10 +228,8 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
// 医嘱定义ID集合
|
// 医嘱定义ID集合
|
||||||
List<Long> adviceDefinitionIdList = adviceBaseDtoList.stream().map(AdviceBaseDto::getAdviceDefinitionId)
|
List<Long> adviceDefinitionIdList = adviceBaseDtoList.stream().map(AdviceBaseDto::getAdviceDefinitionId)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
// 费用定价主表ID集合(过滤null值,手术项目无定价定义)
|
// 费用定价主表ID集合
|
||||||
List<Long> chargeItemDefinitionIdList = adviceBaseDtoList.stream()
|
List<Long> chargeItemDefinitionIdList = adviceBaseDtoList.stream().map(AdviceBaseDto::getChargeItemDefinitionId)
|
||||||
.map(AdviceBaseDto::getChargeItemDefinitionId)
|
|
||||||
.filter(Objects::nonNull)
|
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// 判断是否包含药品或耗材类型(只有这些类型才需要库存相关查询)
|
// 判断是否包含药品或耗材类型(只有这些类型才需要库存相关查询)
|
||||||
@@ -277,9 +275,9 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
medLocationConfig = Collections.emptyList();
|
medLocationConfig = Collections.emptyList();
|
||||||
allowedLocByCategory = Collections.emptyMap();
|
allowedLocByCategory = Collections.emptyMap();
|
||||||
}
|
}
|
||||||
// 费用定价子表信息 - 仅药品/耗材需要批次定价查询,手术/诊疗无库存概念不需要
|
// 费用定价子表信息 - 使用分批处理避免大量参数问题
|
||||||
List<AdvicePriceDto> childCharge = new ArrayList<>();
|
List<AdvicePriceDto> childCharge = new ArrayList<>();
|
||||||
if (hasMedOrDevice && chargeItemDefinitionIdList != null && !chargeItemDefinitionIdList.isEmpty()) {
|
if (chargeItemDefinitionIdList != null && !chargeItemDefinitionIdList.isEmpty()) {
|
||||||
// 分批处理,每批最多1000个ID,增加批次大小以减少查询次数
|
// 分批处理,每批最多1000个ID,增加批次大小以减少查询次数
|
||||||
int batchSize = 1000;
|
int batchSize = 1000;
|
||||||
for (int i = 0; i < chargeItemDefinitionIdList.size(); i += batchSize) {
|
for (int i = 0; i < chargeItemDefinitionIdList.size(); i += batchSize) {
|
||||||
@@ -959,16 +957,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||||
Long requestId = adviceSaveDto.getRequestId();
|
iMedicationRequestService.removeById(adviceSaveDto.getRequestId());
|
||||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的药品请求
|
|
||||||
if (requestId == null) {
|
|
||||||
log.warn("BugFix#442: handMedication - 跳过 requestId 为 null 的删除请求");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
iMedicationRequestService.removeById(requestId);
|
|
||||||
// 删除已经产生的药品发放信息
|
// 删除已经产生的药品发放信息
|
||||||
iMedicationDispenseService.deleteMedicationDispense(adviceSaveDto.getRequestId());
|
iMedicationDispenseService.deleteMedicationDispense(adviceSaveDto.getRequestId());
|
||||||
// 🔧 Bug Fix #219: 删除费用项
|
// 🔧 Bug Fix #219: 删除费用项
|
||||||
|
Long requestId = adviceSaveDto.getRequestId();
|
||||||
String serviceTable = CommonConstants.TableName.MED_MEDICATION_REQUEST;
|
String serviceTable = CommonConstants.TableName.MED_MEDICATION_REQUEST;
|
||||||
// 直接删除费用项
|
// 直接删除费用项
|
||||||
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
||||||
@@ -1424,11 +1417,6 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
log.info("BugFix#219: handDevice - 开始删除循环, deleteList.size={}", deleteList.size());
|
log.info("BugFix#219: handDevice - 开始删除循环, deleteList.size={}", deleteList.size());
|
||||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||||
Long requestId = adviceSaveDto.getRequestId();
|
Long requestId = adviceSaveDto.getRequestId();
|
||||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的耗材请求
|
|
||||||
if (requestId == null) {
|
|
||||||
log.warn("BugFix#442: handDevice - 跳过 requestId 为 null 的删除请求");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
log.info("BugFix#219: handDevice - 删除开始: requestId={}", requestId);
|
log.info("BugFix#219: handDevice - 删除开始: requestId={}", requestId);
|
||||||
|
|
||||||
// 1. 删除耗材请求
|
// 1. 删除耗材请求
|
||||||
@@ -1539,22 +1527,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
deviceRequest.setRequesterId(adviceSaveDto.getPractitionerId()); // 开方医生
|
deviceRequest.setRequesterId(adviceSaveDto.getPractitionerId()); // 开方医生
|
||||||
deviceRequest.setOrgId(adviceSaveDto.getFounderOrgId());// 开方人科室
|
deviceRequest.setOrgId(adviceSaveDto.getFounderOrgId());// 开方人科室
|
||||||
deviceRequest.setReqAuthoredTime(curDate); // 请求开始时间
|
deviceRequest.setReqAuthoredTime(curDate); // 请求开始时间
|
||||||
// 发放耗材房(若前端未传locationId,优先沿用已有DeviceRequest的performLocation,否则使用登录用户科室)
|
// 发放耗材房(若前端未传locationId,使用登录用户的科室作为默认值)
|
||||||
Long locId = adviceSaveDto.getLocationId();
|
Long locId = adviceSaveDto.getLocationId();
|
||||||
if (locId == null) {
|
if (locId == null) {
|
||||||
// 尝试从已有DeviceRequest获取原始的performLocation
|
locId = SecurityUtils.getLoginUser().getOrgId();
|
||||||
if (adviceSaveDto.getRequestId() != null) {
|
log.info("耗材locationId为空,使用登录用户科室作为默认值: locationId={}", locId);
|
||||||
DeviceRequest existingDevice = iDeviceRequestService.getById(adviceSaveDto.getRequestId());
|
|
||||||
if (existingDevice != null && existingDevice.getPerformLocation() != null) {
|
|
||||||
locId = existingDevice.getPerformLocation();
|
|
||||||
log.info("耗材locationId为空,使用已有DeviceRequest的performLocation: locationId={}", locId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 如果已有记录也没有performLocation,则使用登录用户科室作为兜底
|
|
||||||
if (locId == null) {
|
|
||||||
locId = SecurityUtils.getLoginUser().getOrgId();
|
|
||||||
log.info("耗材locationId为空且无已有记录,使用登录用户科室作为默认值: locationId={}", locId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
deviceRequest.setPerformLocation(locId);
|
deviceRequest.setPerformLocation(locId);
|
||||||
deviceRequest.setEncounterId(adviceSaveDto.getEncounterId()); // 就诊id
|
deviceRequest.setEncounterId(adviceSaveDto.getEncounterId()); // 就诊id
|
||||||
@@ -1744,17 +1721,12 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
for (AdviceSaveDto adviceSaveDto : deleteList) {
|
||||||
Long requestId = adviceSaveDto.getRequestId();
|
iServiceRequestService.removeById(adviceSaveDto.getRequestId());// 删除诊疗
|
||||||
// 🔧 Bug #442: 跳过 requestId 为 null 的记录,避免删除不存在的诊疗请求
|
|
||||||
if (requestId == null) {
|
|
||||||
log.warn("BugFix#442: handService - 跳过 requestId 为 null 的删除请求");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
iServiceRequestService.removeById(requestId);// 删除诊疗
|
|
||||||
iServiceRequestService.remove(
|
iServiceRequestService.remove(
|
||||||
new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getParentId,
|
new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getParentId,
|
||||||
requestId));// 删除诊疗套餐对应的子项
|
adviceSaveDto.getRequestId()));// 删除诊疗套餐对应的子项
|
||||||
// 🔧 Bug Fix #219: 删除费用项
|
// 🔧 Bug Fix #219: 删除费用项
|
||||||
|
Long requestId = adviceSaveDto.getRequestId();
|
||||||
String serviceTable = CommonConstants.TableName.WOR_SERVICE_REQUEST;
|
String serviceTable = CommonConstants.TableName.WOR_SERVICE_REQUEST;
|
||||||
// 直接删除费用项
|
// 直接删除费用项
|
||||||
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
iChargeItemService.deleteByServiceTableAndId(serviceTable, requestId);
|
||||||
@@ -1811,9 +1783,8 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
log.info("handService - 自动补全founderOrgId: founderOrgId={}", adviceSaveDto.getFounderOrgId());
|
log.info("handService - 自动补全founderOrgId: founderOrgId={}", adviceSaveDto.getFounderOrgId());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔧 Bug Fix #238/#454: 诊疗项目执行科室非空校验(删除操作跳过校验)
|
// 🔧 Bug Fix #238: 诊疗项目执行科室非空校验
|
||||||
if (adviceSaveDto.getAdviceType() != null && adviceSaveDto.getAdviceType() == 3
|
if (adviceSaveDto.getAdviceType() != null && adviceSaveDto.getAdviceType() == 3) {
|
||||||
&& !DbOpType.DELETE.getCode().equals(adviceSaveDto.getDbOpType())) {
|
|
||||||
Long effectiveOrgId = adviceSaveDto.getEffectiveOrgId();
|
Long effectiveOrgId = adviceSaveDto.getEffectiveOrgId();
|
||||||
if (effectiveOrgId == null) {
|
if (effectiveOrgId == null) {
|
||||||
throw new ServiceException("诊疗项目必须选择执行科室");
|
throw new ServiceException("诊疗项目必须选择执行科室");
|
||||||
@@ -2016,25 +1987,13 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public R<?> getRequestBaseInfo(Long encounterId) {
|
public R<?> getRequestBaseInfo(Long encounterId) {
|
||||||
return this.getRequestBaseInfo(encounterId, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public R<?> getRequestBaseInfo(Long encounterId, Integer generateSourceEnum, String sourceBillNo) {
|
|
||||||
// 当前账号的参与者id
|
// 当前账号的参与者id
|
||||||
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
||||||
// 未指定generateSourceEnum时,默认只查询医生开立的医嘱
|
|
||||||
int sourceEnum = (generateSourceEnum != null) ? generateSourceEnum : GenerateSource.DOCTOR_PRESCRIPTION.getValue();
|
|
||||||
// 医嘱请求数据
|
// 医嘱请求数据
|
||||||
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, null,
|
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, null,
|
||||||
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
||||||
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.NO.getCode(),
|
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.NO.getCode(),
|
||||||
sourceEnum, sourceBillNo);
|
GenerateSource.DOCTOR_PRESCRIPTION.getValue());
|
||||||
// 手术计费场景:sourceBillNo 不为空时,只保留诊疗请求(3/6),过滤掉药品(1)和耗材(2)
|
|
||||||
if (sourceBillNo != null && !sourceBillNo.isEmpty()) {
|
|
||||||
requestBaseInfo.removeIf(dto -> dto.getAdviceType() != null
|
|
||||||
&& (dto.getAdviceType() == 1 || dto.getAdviceType() == 2));
|
|
||||||
}
|
|
||||||
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
||||||
// 请求状态
|
// 请求状态
|
||||||
requestBaseDto
|
requestBaseDto
|
||||||
@@ -2155,7 +2114,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, patientId,
|
List<RequestBaseDto> requestBaseInfo = doctorStationAdviceAppMapper.getRequestBaseInfo(encounterId, patientId,
|
||||||
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
||||||
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.YES.getCode(),
|
CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.YES.getCode(),
|
||||||
GenerateSource.DOCTOR_PRESCRIPTION.getValue(), null);
|
GenerateSource.DOCTOR_PRESCRIPTION.getValue());
|
||||||
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
for (RequestBaseDto requestBaseDto : requestBaseInfo) {
|
||||||
// 请求状态
|
// 请求状态
|
||||||
requestBaseDto
|
requestBaseDto
|
||||||
|
|||||||
@@ -580,11 +580,7 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
|
|||||||
@Override
|
@Override
|
||||||
public R<?> saveInfectiousDiseaseReport(InfectiousDiseaseReportDto infectiousDiseaseReportDto) {
|
public R<?> saveInfectiousDiseaseReport(InfectiousDiseaseReportDto infectiousDiseaseReportDto) {
|
||||||
// 检查卡片编号唯一性(新增时检查,编辑时排除当前记录)
|
// 检查卡片编号唯一性(新增时检查,编辑时排除当前记录)
|
||||||
String cardNo = infectiousDiseaseReportDto.getCardNo();
|
String cardNo = infectiousDiseaseReportDto.getCardNo().trim();
|
||||||
if (cardNo == null || cardNo.trim().isEmpty()) {
|
|
||||||
return R.fail("卡片编号不能为空");
|
|
||||||
}
|
|
||||||
cardNo = cardNo.trim();
|
|
||||||
LambdaQueryWrapper<InfectiousDiseaseReport> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<InfectiousDiseaseReport> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(InfectiousDiseaseReport::getCardNo, cardNo);
|
queryWrapper.eq(InfectiousDiseaseReport::getCardNo, cardNo);
|
||||||
long count = iInfectiousDiseaseReportService.count(queryWrapper);
|
long count = iInfectiousDiseaseReportService.count(queryWrapper);
|
||||||
|
|||||||
@@ -274,8 +274,27 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
|
|||||||
return R.fail("非就诊中患者不能完诊");
|
return R.fail("非就诊中患者不能完诊");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查找队列项(限定当天,避免复诊患者匹配到历史队列记录)
|
// 2. 获取 pool_id 和 slot_id:从 encounter → order_main → adm_schedule_slot 链路获取
|
||||||
|
// 确保 div_log 中的值与排班主表一致,不依赖 triage_queue_item(队列项可能不存在或值错误)
|
||||||
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
|
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
|
||||||
|
Long divPoolId = null;
|
||||||
|
Long divSlotId = null;
|
||||||
|
if (encounter.getOrderId() != null) {
|
||||||
|
try {
|
||||||
|
Order order = iOrderService.getById(encounter.getOrderId());
|
||||||
|
if (order != null && order.getSlotId() != null) {
|
||||||
|
divSlotId = order.getSlotId();
|
||||||
|
ScheduleSlot slot = scheduleSlotMapper.selectById(divSlotId);
|
||||||
|
if (slot != null) {
|
||||||
|
divPoolId = slot.getPoolId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("获取完诊div_log的pool_id/slot_id失败,encounterId={}", encounterId, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 查找队列项(限定当天,避免复诊患者匹配到历史队列记录)
|
||||||
TriageQueueItem queueItem = triageQueueItemService.getOne(
|
TriageQueueItem queueItem = triageQueueItemService.getOne(
|
||||||
new LambdaQueryWrapper<TriageQueueItem>()
|
new LambdaQueryWrapper<TriageQueueItem>()
|
||||||
.eq(TriageQueueItem::getTenantId, tenantId)
|
.eq(TriageQueueItem::getTenantId, tenantId)
|
||||||
@@ -300,67 +319,33 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 获取 pool_id 和 slot_id:优先使用 triage_queue_item(挂号时录入的号源信息,为权威来源)
|
|
||||||
// 队列项不存在或值缺失时,回退使用 encounter → order_main → adm_schedule_slot 链路
|
|
||||||
Long divPoolId = null;
|
|
||||||
Long divSlotId = null;
|
|
||||||
if (queueItem != null && queueItem.getPoolId() != null && queueItem.getSlotId() != null) {
|
|
||||||
divPoolId = queueItem.getPoolId();
|
|
||||||
divSlotId = queueItem.getSlotId();
|
|
||||||
}
|
|
||||||
// 队列项 poolId/slotId 缺失时,通过 encounter.orderId → order_main.slot_id → adm_schedule_slot.pool_id 回退获取
|
|
||||||
if ((divPoolId == null || divSlotId == null) && encounter.getOrderId() != null) {
|
|
||||||
try {
|
|
||||||
Order order = iOrderService.getById(encounter.getOrderId());
|
|
||||||
if (order != null && order.getSlotId() != null) {
|
|
||||||
ScheduleSlot slot = scheduleSlotMapper.selectById(order.getSlotId());
|
|
||||||
if (slot != null) {
|
|
||||||
divSlotId = slot.getId();
|
|
||||||
divPoolId = slot.getPoolId();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.warn("回退获取完诊div_log的pool_id/slot_id失败,encounterId={}", encounterId, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果队列项存在且未完成,更新队列状态为已完成
|
// 如果队列项存在且未完成,更新队列状态为已完成
|
||||||
// 使用排除法而非白名单:只要不是"已完成"就可以完诊,覆盖跳过、等待等非标准流转状态
|
// 使用排除法而非白名单:只要不是"已完成"就可以完诊,覆盖跳过、等待等非标准流转状态
|
||||||
if (queueItem != null &&
|
if (queueItem != null &&
|
||||||
!TriageQueueStatus.COMPLETED.getValue().equals(queueItem.getStatus())) {
|
!TriageQueueStatus.COMPLETED.getValue().equals(queueItem.getStatus())) {
|
||||||
java.time.LocalDateTime nowLocal = java.time.LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
|
java.time.LocalDateTime nowLocal = java.time.LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
|
||||||
// 使用 LambdaUpdateWrapper 直接更新,确保 status 字段必定写入数据库
|
queueItem.setStatus(TriageQueueStatus.COMPLETED.getValue());
|
||||||
boolean queueUpdate = triageQueueItemService.update(new LambdaUpdateWrapper<TriageQueueItem>()
|
queueItem.setUpdateTime(nowLocal);
|
||||||
.eq(TriageQueueItem::getId, queueItem.getId())
|
triageQueueItemService.updateById(queueItem);
|
||||||
.set(TriageQueueItem::getStatus, TriageQueueStatus.COMPLETED.getValue())
|
|
||||||
.set(TriageQueueItem::getUpdateTime, nowLocal));
|
|
||||||
if (!queueUpdate) {
|
|
||||||
log.error("完诊:triage_queue_item 状态更新失败,queueItemId={}", queueItem.getId());
|
|
||||||
}
|
|
||||||
} else if (queueItem == null) {
|
} else if (queueItem == null) {
|
||||||
log.error("完诊:未找到任何 triage_queue_item 记录,encounterId={}, tenantId={}",
|
log.error("完诊:未找到任何 triage_queue_item 记录,encounterId={}, tenantId={}",
|
||||||
encounterId, tenantId);
|
encounterId, tenantId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 写入 div_log 审计日志(独立于队列项,确保每次完诊都生成记录)
|
// 写入 div_log 审计日志(独立于队列项,确保每次完诊都生成记录)
|
||||||
// 防重复:若队列项已是 COMPLETED 状态,说明护士站已处理过并写过分诊日志,不再重复写入
|
try {
|
||||||
boolean queueAlreadyCompleted = queueItem != null
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
&& TriageQueueStatus.COMPLETED.getValue().equals(queueItem.getStatus());
|
DivLog divLog = new DivLog()
|
||||||
if (!queueAlreadyCompleted) {
|
.setPoolId(divPoolId)
|
||||||
try {
|
.setSlotId(divSlotId)
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
.setOpUserId(loginUser != null ? loginUser.getUserId() : null)
|
||||||
DivLog divLog = new DivLog()
|
.setAction("COMPLETE")
|
||||||
.setPoolId(divPoolId)
|
.setCreateTime(LocalDateTime.now())
|
||||||
.setSlotId(divSlotId)
|
.setUpdateAt(LocalDateTime.now())
|
||||||
.setOpUserId(loginUser != null ? loginUser.getUserId() : null)
|
.setCreatedAt(LocalDateTime.now());
|
||||||
.setAction("COMPLETE")
|
divLogService.save(divLog);
|
||||||
.setCreateTime(LocalDateTime.now())
|
} catch (Exception e) {
|
||||||
.setUpdateAt(LocalDateTime.now())
|
log.error("写入div_log审计日志失败", e);
|
||||||
.setCreatedAt(LocalDateTime.now());
|
|
||||||
divLogService.save(divLog);
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("写入div_log审计日志失败", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 更新状态、完成时间以及初复诊标识
|
// 4. 更新状态、完成时间以及初复诊标识
|
||||||
|
|||||||
@@ -112,16 +112,11 @@ public class DoctorStationAdviceController {
|
|||||||
* 查询医嘱请求数据
|
* 查询医嘱请求数据
|
||||||
*
|
*
|
||||||
* @param encounterId 就诊id
|
* @param encounterId 就诊id
|
||||||
* @param generateSourceEnum 生成来源(可选,用于按来源过滤,如手术计费=6)
|
|
||||||
* @param sourceBillNo 来源业务单据号(可选,用于按来源单据过滤)
|
|
||||||
* @return 医嘱请求数据
|
* @return 医嘱请求数据
|
||||||
*/
|
*/
|
||||||
@GetMapping(value = "/request-base-info")
|
@GetMapping(value = "/request-base-info")
|
||||||
public R<?> getRequestBaseInfo(
|
public R<?> getRequestBaseInfo(@RequestParam(required = false) Long encounterId) {
|
||||||
@RequestParam(required = false) Long encounterId,
|
return iDoctorStationAdviceAppService.getRequestBaseInfo(encounterId);
|
||||||
@RequestParam(required = false) Integer generateSourceEnum,
|
|
||||||
@RequestParam(required = false) String sourceBillNo) {
|
|
||||||
return iDoctorStationAdviceAppService.getRequestBaseInfo(encounterId, generateSourceEnum, sourceBillNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -122,8 +122,7 @@ public interface DoctorStationAdviceAppMapper {
|
|||||||
@Param("MED_MEDICATION_REQUEST") String MED_MEDICATION_REQUEST,
|
@Param("MED_MEDICATION_REQUEST") String MED_MEDICATION_REQUEST,
|
||||||
@Param("WOR_DEVICE_REQUEST") String WOR_DEVICE_REQUEST,
|
@Param("WOR_DEVICE_REQUEST") String WOR_DEVICE_REQUEST,
|
||||||
@Param("WOR_SERVICE_REQUEST") String WOR_SERVICE_REQUEST, @Param("practitionerId") Long practitionerId,
|
@Param("WOR_SERVICE_REQUEST") String WOR_SERVICE_REQUEST, @Param("practitionerId") Long practitionerId,
|
||||||
@Param("historyFlag") String historyFlag, @Param("generateSourceEnum") Integer generateSourceEnum,
|
@Param("historyFlag") String historyFlag, @Param("generateSourceEnum") Integer generateSourceEnum);
|
||||||
@Param("sourceBillNo") String sourceBillNo);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询就诊费用性质
|
* 查询就诊费用性质
|
||||||
|
|||||||
@@ -178,26 +178,15 @@ public class AdviceUtils {
|
|||||||
// 生命提示信息集合
|
// 生命提示信息集合
|
||||||
List<String> tipsList = new ArrayList<>();
|
List<String> tipsList = new ArrayList<>();
|
||||||
for (MedicationRequestUseExe medicationRequestUseExe : medUseExeList) {
|
for (MedicationRequestUseExe medicationRequestUseExe : medUseExeList) {
|
||||||
// 第一步:按 performLocation 匹配指定药房的库存
|
// 聚合同一位置所有批次的库存总量
|
||||||
List<AdviceInventoryDto> matchedInventories = adviceInventory.stream()
|
List<AdviceInventoryDto> matchedInventories = adviceInventory.stream()
|
||||||
.filter(inventoryDto -> medicationRequestUseExe.getMedicationId().equals(inventoryDto.getItemId())
|
.filter(inventoryDto -> medicationRequestUseExe.getMedicationId().equals(inventoryDto.getItemId())
|
||||||
&& CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(inventoryDto.getItemTable())
|
&& CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(inventoryDto.getItemTable())
|
||||||
&& (medicationRequestUseExe.getPerformLocation() == null
|
&& medicationRequestUseExe.getPerformLocation().equals(inventoryDto.getLocationId())
|
||||||
|| medicationRequestUseExe.getPerformLocation().equals(inventoryDto.getLocationId()))
|
|
||||||
// 如果选择了具体的批次号,校验库存时需要加上批次号的匹配条件
|
// 如果选择了具体的批次号,校验库存时需要加上批次号的匹配条件
|
||||||
&& (StringUtils.isEmpty(medicationRequestUseExe.getLotNumber())
|
&& (StringUtils.isEmpty(medicationRequestUseExe.getLotNumber())
|
||||||
|| medicationRequestUseExe.getLotNumber().equals(inventoryDto.getLotNumber())))
|
|| medicationRequestUseExe.getLotNumber().equals(inventoryDto.getLotNumber())))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
// 第二步:如果指定药房没有匹配到库存,则放宽条件查询所有药房的库存
|
|
||||||
if (matchedInventories.isEmpty()) {
|
|
||||||
matchedInventories = adviceInventory.stream()
|
|
||||||
.filter(inventoryDto -> medicationRequestUseExe.getMedicationId().equals(inventoryDto.getItemId())
|
|
||||||
&& CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(inventoryDto.getItemTable())
|
|
||||||
// 如果选择了具体的批次号,校验库存时需要加上批次号的匹配条件
|
|
||||||
&& (StringUtils.isEmpty(medicationRequestUseExe.getLotNumber())
|
|
||||||
|| medicationRequestUseExe.getLotNumber().equals(inventoryDto.getLotNumber())))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
// 匹配到库存信息
|
// 匹配到库存信息
|
||||||
if (!matchedInventories.isEmpty()) {
|
if (!matchedInventories.isEmpty()) {
|
||||||
// 聚合所有批次的可用库存
|
// 聚合所有批次的可用库存
|
||||||
|
|||||||
@@ -341,7 +341,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
|||||||
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// 防重复保存:对所有医嘱进行去重(包括 INSERT 和 UPDATE 混合场景),避免签发单条医嘱时产生重复记录
|
// 防重复保存:对新增医嘱进行去重,避免签发单条长期医嘱时产生重复记录
|
||||||
Set<String> longUniqueKeySet = new HashSet<>();
|
Set<String> longUniqueKeySet = new HashSet<>();
|
||||||
List<RegAdviceSaveDto> longUniqueList = new ArrayList<>();
|
List<RegAdviceSaveDto> longUniqueList = new ArrayList<>();
|
||||||
for (RegAdviceSaveDto adviceSaveDto : longInsertOrUpdateList) {
|
for (RegAdviceSaveDto adviceSaveDto : longInsertOrUpdateList) {
|
||||||
@@ -351,10 +351,10 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
|||||||
+ adviceSaveDto.getDose() + "_"
|
+ adviceSaveDto.getDose() + "_"
|
||||||
+ adviceSaveDto.getMethodCode() + "_"
|
+ adviceSaveDto.getMethodCode() + "_"
|
||||||
+ adviceSaveDto.getRateCode();
|
+ adviceSaveDto.getRateCode();
|
||||||
if (longUniqueKeySet.contains(uniqueKey)) {
|
if (DbOpType.INSERT.getCode().equals(adviceSaveDto.getDbOpType()) && longUniqueKeySet.contains(uniqueKey)) {
|
||||||
log.warn("防重复保存:检测到重复长期医嘱(跨操作类型),跳过 - patientId={}, encounterId={}, adviceDefinitionId={}, dbOpType={}",
|
log.warn("防重复保存:检测到重复长期医嘱,跳过保存 - patientId={}, encounterId={}, adviceDefinitionId={}, dose={}",
|
||||||
adviceSaveDto.getPatientId(), adviceSaveDto.getEncounterId(),
|
adviceSaveDto.getPatientId(), adviceSaveDto.getEncounterId(),
|
||||||
adviceSaveDto.getAdviceDefinitionId(), adviceSaveDto.getDbOpType());
|
adviceSaveDto.getAdviceDefinitionId(), adviceSaveDto.getDose());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
longUniqueKeySet.add(uniqueKey);
|
longUniqueKeySet.add(uniqueKey);
|
||||||
@@ -429,7 +429,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
|||||||
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// 防重复保存:对所有医嘱进行去重(包括 INSERT 和 UPDATE 混合场景),避免签发时产生重复记录
|
// 防重复保存:对新增医嘱进行去重
|
||||||
Set<String> tempUniqueKeySet = new HashSet<>();
|
Set<String> tempUniqueKeySet = new HashSet<>();
|
||||||
List<RegAdviceSaveDto> tempUniqueList = new ArrayList<>();
|
List<RegAdviceSaveDto> tempUniqueList = new ArrayList<>();
|
||||||
for (RegAdviceSaveDto adviceSaveDto : tempInsertOrUpdateList) {
|
for (RegAdviceSaveDto adviceSaveDto : tempInsertOrUpdateList) {
|
||||||
@@ -439,10 +439,10 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
|||||||
+ adviceSaveDto.getDose() + "_"
|
+ adviceSaveDto.getDose() + "_"
|
||||||
+ adviceSaveDto.getMethodCode() + "_"
|
+ adviceSaveDto.getMethodCode() + "_"
|
||||||
+ adviceSaveDto.getRateCode();
|
+ adviceSaveDto.getRateCode();
|
||||||
if (tempUniqueKeySet.contains(uniqueKey)) {
|
if (DbOpType.INSERT.getCode().equals(adviceSaveDto.getDbOpType()) && tempUniqueKeySet.contains(uniqueKey)) {
|
||||||
log.warn("防重复保存:检测到重复临时医嘱(跨操作类型),跳过 - patientId={}, encounterId={}, adviceDefinitionId={}, dbOpType={}",
|
log.warn("防重复保存:检测到重复临时医嘱,跳过保存 - patientId={}, encounterId={}, adviceDefinitionId={}, dose={}",
|
||||||
adviceSaveDto.getPatientId(), adviceSaveDto.getEncounterId(),
|
adviceSaveDto.getPatientId(), adviceSaveDto.getEncounterId(),
|
||||||
adviceSaveDto.getAdviceDefinitionId(), adviceSaveDto.getDbOpType());
|
adviceSaveDto.getAdviceDefinitionId(), adviceSaveDto.getDose());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tempUniqueKeySet.add(uniqueKey);
|
tempUniqueKeySet.add(uniqueKey);
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -76,34 +75,12 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
|||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public R<?> saveRequestForm(RequestFormSaveDto requestFormSaveDto, String typeCode) {
|
public R<?> saveRequestForm(RequestFormSaveDto requestFormSaveDto, String typeCode) {
|
||||||
// 申请单ID(前端空字符串可能反序列化为0L,需同时判0)
|
|
||||||
Long requestFormId = requestFormSaveDto.getRequestFormId();
|
|
||||||
boolean isEdit = requestFormId != null && requestFormId != 0L;
|
|
||||||
|
|
||||||
// 诊疗执行科室配置校验(必须在任何数据库操作之前)
|
|
||||||
List<ActivityOrganizationConfigDto> activityOrganizationConfig =
|
|
||||||
requestFormManageAppMapper.getActivityOrganizationConfig(typeCode);
|
|
||||||
if (activityOrganizationConfig.isEmpty()) {
|
|
||||||
throw new ServiceException("请先配置当前时间段的执行科室");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 逐个校验activityList中的项目是否都配置了执行科室,避免部分通过后在循环中抛异常导致事务复杂化
|
|
||||||
List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList();
|
|
||||||
if (activityList != null && !activityList.isEmpty()) {
|
|
||||||
for (ActivitySaveDto activitySaveDto : activityList) {
|
|
||||||
Long positionId = activityOrganizationConfig.stream()
|
|
||||||
.filter(dto -> activitySaveDto.getAdviceDefinitionId().equals(dto.getActivityDefinitionId()))
|
|
||||||
.map(ActivityOrganizationConfigDto::getOrganizationId).findFirst().orElse(null);
|
|
||||||
if (positionId == null) {
|
|
||||||
throw new ServiceException(activitySaveDto.getAdviceDefinitionName() + "未配置当前时间段的执行科室");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 诊疗处方号
|
// 诊疗处方号
|
||||||
String prescriptionNo;
|
String prescriptionNo;
|
||||||
|
// 申请单ID
|
||||||
|
Long requestFormId = requestFormSaveDto.getRequestFormId();
|
||||||
// 编辑场景
|
// 编辑场景
|
||||||
if (isEdit) {
|
if (requestFormId != null) {
|
||||||
RequestForm requestFormInfo = iRequestFormService.getById(requestFormId);
|
RequestForm requestFormInfo = iRequestFormService.getById(requestFormId);
|
||||||
prescriptionNo = requestFormInfo.getPrescriptionNo();
|
prescriptionNo = requestFormInfo.getPrescriptionNo();
|
||||||
// 该申请单存在的待发送医嘱个数
|
// 该申请单存在的待发送医嘱个数
|
||||||
@@ -114,10 +91,8 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
|||||||
return R.fail("无待签发的医嘱,该申请单不可编辑");
|
return R.fail("无待签发的医嘱,该申请单不可编辑");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 检查申请单号:JC(检查)+ Z(住院标识)+ yyMMdd(日期)+ 5位顺序号
|
// 诊疗处方号
|
||||||
String dateStr = new java.text.SimpleDateFormat("yyMMdd").format(new Date());
|
prescriptionNo = assignSeqUtil.getSeq(AssignSeqEnum.ACTIVITY_PSYCHOTROPIC_NO.getPrefix(), 8);
|
||||||
int seq = assignSeqUtil.getSeqNoByDay(AssignSeqEnum.CHECK_APPLY_NO.getPrefix());
|
|
||||||
prescriptionNo = "JCZ" + dateStr + String.format("%05d", seq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当前时间
|
// 当前时间
|
||||||
@@ -147,7 +122,7 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
|||||||
iRequestFormService.saveOrUpdate(requestForm);
|
iRequestFormService.saveOrUpdate(requestForm);
|
||||||
|
|
||||||
// 编辑场景时,先删除掉原有诊疗项目及账单再新增
|
// 编辑场景时,先删除掉原有诊疗项目及账单再新增
|
||||||
if (isEdit) {
|
if (requestFormId != null) {
|
||||||
List<Long> serviceRequestIds = iServiceRequestService
|
List<Long> serviceRequestIds = iServiceRequestService
|
||||||
.list(new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getPrescriptionNo, prescriptionNo))
|
.list(new LambdaQueryWrapper<ServiceRequest>().eq(ServiceRequest::getPrescriptionNo, prescriptionNo))
|
||||||
.stream().map(ServiceRequest::getId).collect(Collectors.toList());
|
.stream().map(ServiceRequest::getId).collect(Collectors.toList());
|
||||||
@@ -161,7 +136,15 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
|||||||
|
|
||||||
ServiceRequest serviceRequest;
|
ServiceRequest serviceRequest;
|
||||||
ChargeItem chargeItem;
|
ChargeItem chargeItem;
|
||||||
|
// 诊疗集合
|
||||||
|
List<ActivitySaveDto> activityList = requestFormSaveDto.getActivityList();
|
||||||
log.info("保存申请单,typeCode={}, activityListSize={}, encounterId={}", typeCode, activityList != null ? activityList.size() : 0, encounterId);
|
log.info("保存申请单,typeCode={}, activityListSize={}, encounterId={}", typeCode, activityList != null ? activityList.size() : 0, encounterId);
|
||||||
|
// 诊疗执行科室配置
|
||||||
|
List<ActivityOrganizationConfigDto> activityOrganizationConfig =
|
||||||
|
requestFormManageAppMapper.getActivityOrganizationConfig(typeCode);
|
||||||
|
if (activityOrganizationConfig.isEmpty()) {
|
||||||
|
throw new ServiceException("请先配置当前时间段的执行科室");
|
||||||
|
}
|
||||||
|
|
||||||
for (ActivitySaveDto activitySaveDto : activityList) {
|
for (ActivitySaveDto activitySaveDto : activityList) {
|
||||||
serviceRequest = new ServiceRequest();
|
serviceRequest = new ServiceRequest();
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,23 +81,14 @@ public class RequestFormManageController {
|
|||||||
* 查询检查申请单
|
* 查询检查申请单
|
||||||
*
|
*
|
||||||
* @param encounterId 就诊id
|
* @param encounterId 就诊id
|
||||||
* @param startDate 开始日期(可选,格式:yyyy-MM-dd)
|
|
||||||
* @param endDate 结束日期(可选,格式:yyyy-MM-dd)
|
|
||||||
* @param status 单据状态(可选)
|
|
||||||
* @param keyword 关键字(可选,申请单号/检查项目名称模糊匹配)
|
|
||||||
* @return 检查申请单
|
* @return 检查申请单
|
||||||
*/
|
*/
|
||||||
@GetMapping(value = "/get-check")
|
@GetMapping(value = "/get-check")
|
||||||
public R<?> getCheckRequestForm(
|
public R<?> getCheckRequestForm(@RequestParam(required = false) Long encounterId) {
|
||||||
@RequestParam(required = false) Long encounterId,
|
|
||||||
@RequestParam(required = false) String startDate,
|
|
||||||
@RequestParam(required = false) String endDate,
|
|
||||||
@RequestParam(required = false) String status,
|
|
||||||
@RequestParam(required = false) String keyword) {
|
|
||||||
if (encounterId == null) {
|
if (encounterId == null) {
|
||||||
return R.fail("就诊ID不能为空");
|
return R.fail("就诊ID不能为空");
|
||||||
}
|
}
|
||||||
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.TEST.getCode(), startDate, endDate, status, keyword));
|
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.TEST.getCode()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -152,32 +142,6 @@ public class RequestFormManageController {
|
|||||||
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROCEDURE.getCode()));
|
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROCEDURE.getCode()));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 分页查询手术申请单(全局,不需要encounterId,用于门诊手术安排查找弹窗)
|
|
||||||
*
|
|
||||||
* @param surgeryNo 手术单号(模糊查询,可选)
|
|
||||||
* @param applyTimeStart 申请时间起始(可选)
|
|
||||||
* @param applyTimeEnd 申请时间截止(可选)
|
|
||||||
* @param mainDoctorId 主刀医生ID(可选)
|
|
||||||
* @param applyDeptId 申请科室ID(可选)
|
|
||||||
* @param pageNo 页码,默认1
|
|
||||||
* @param pageSize 每页数量,默认10
|
|
||||||
* @return 分页手术申请单列表
|
|
||||||
*/
|
|
||||||
@GetMapping(value = "/get-surgery-page")
|
|
||||||
public R<IPage<RequestFormPageDto>> getSurgeryRequestFormPage(
|
|
||||||
@RequestParam(required = false) String surgeryNo,
|
|
||||||
@RequestParam(required = false) LocalDate applyTimeStart,
|
|
||||||
@RequestParam(required = false) LocalDate applyTimeEnd,
|
|
||||||
@RequestParam(required = false) Long mainDoctorId,
|
|
||||||
@RequestParam(required = false) Long applyDeptId,
|
|
||||||
@RequestParam(defaultValue = "1") Integer pageNo,
|
|
||||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
|
||||||
RequestFormDto dto = new RequestFormDto(surgeryNo, ActivityDefCategory.PROCEDURE.getCode(), applyTimeStart, applyTimeEnd,
|
|
||||||
mainDoctorId, applyDeptId, pageNo, pageSize);
|
|
||||||
return R.ok(iRequestFormManageAppService.getRequestFormPage(dto));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页查询申请单
|
* 分页查询申请单
|
||||||
* @return 申请单
|
* @return 申请单
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,10 +14,6 @@ public class RequestFormDto {
|
|||||||
* 手术单号
|
* 手术单号
|
||||||
*/
|
*/
|
||||||
private String surgeryNo;
|
private String surgeryNo;
|
||||||
/**
|
|
||||||
* 申请单类型编码
|
|
||||||
*/
|
|
||||||
private String typeCode;
|
|
||||||
/**
|
/**
|
||||||
* 申请时间开始
|
* 申请时间开始
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -138,12 +138,4 @@ public class CurrentDayEncounterTencentDto {
|
|||||||
*/
|
*/
|
||||||
private String englishName;
|
private String englishName;
|
||||||
|
|
||||||
/** 号源池ID(用于分诊队列 div_log 审计日志) */
|
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
|
||||||
private Long poolId;
|
|
||||||
|
|
||||||
/** 号源槽位ID(用于分诊队列 div_log 审计日志) */
|
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
|
||||||
private Long slotId;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,12 +89,15 @@
|
|||||||
cs.apply_doctor_name AS apply_doctor_name,
|
cs.apply_doctor_name AS apply_doctor_name,
|
||||||
drf.create_time AS apply_time,
|
drf.create_time AS apply_time,
|
||||||
os.surgery_nature AS surgeryType,
|
os.surgery_nature AS surgeryType,
|
||||||
os.fee_type AS feeType,
|
fc.contract_name AS feeType,
|
||||||
COALESCE(pi.identifier_no, ap.bus_no, '') AS identifierNo
|
COALESCE(pi.identifier_no, ap.bus_no, '') AS identifierNo
|
||||||
FROM op_schedule os
|
FROM op_schedule os
|
||||||
LEFT JOIN adm_patient ap ON os.patient_id = ap.id
|
LEFT JOIN adm_patient ap ON os.patient_id = ap.id
|
||||||
INNER JOIN cli_surgery cs ON os.oper_code = cs.surgery_no AND cs.delete_flag = '0'
|
INNER JOIN cli_surgery cs ON os.oper_code = cs.surgery_no AND cs.delete_flag = '0'
|
||||||
LEFT JOIN adm_organization o ON cs.org_id = o.id
|
LEFT JOIN adm_organization o ON cs.org_id = o.id
|
||||||
|
LEFT JOIN adm_encounter ae ON ae.id = cs.encounter_id AND ae.delete_flag = '0'
|
||||||
|
LEFT JOIN adm_account aa ON aa.encounter_id = ae.id AND aa.delete_flag = '0'
|
||||||
|
LEFT JOIN fin_contract fc ON fc.bus_no = aa.contract_no AND fc.delete_flag = '0'
|
||||||
LEFT JOIN doc_request_form drf ON drf.prescription_no=cs.surgery_no
|
LEFT JOIN doc_request_form drf ON drf.prescription_no=cs.surgery_no
|
||||||
LEFT JOIN (
|
LEFT JOIN (
|
||||||
SELECT patient_id, identifier_no
|
SELECT patient_id, identifier_no
|
||||||
|
|||||||
@@ -527,9 +527,6 @@
|
|||||||
LEFT JOIN cli_condition AS cc ON cc.id = T1.condition_id AND cc.delete_flag = '0'
|
LEFT JOIN cli_condition AS cc ON cc.id = T1.condition_id AND cc.delete_flag = '0'
|
||||||
LEFT JOIN cli_condition_definition AS ccd ON ccd.id = cc.definition_id
|
LEFT JOIN cli_condition_definition AS ccd ON ccd.id = cc.definition_id
|
||||||
WHERE T1.delete_flag = '0' AND T1.tcm_flag = 0
|
WHERE T1.delete_flag = '0' AND T1.tcm_flag = 0
|
||||||
<if test="generateSourceEnum != null">
|
|
||||||
AND T1.generate_source_enum = #{generateSourceEnum}
|
|
||||||
</if>
|
|
||||||
<if test="historyFlag == '0'.toString()">
|
<if test="historyFlag == '0'.toString()">
|
||||||
AND T1.encounter_id = #{encounterId}
|
AND T1.encounter_id = #{encounterId}
|
||||||
</if>
|
</if>
|
||||||
@@ -698,9 +695,6 @@
|
|||||||
-- based_on_table='med_medication_request' → 输液/皮试执行记录,应排除
|
-- based_on_table='med_medication_request' → 输液/皮试执行记录,应排除
|
||||||
-- based_on_table='exam_apply'/'lab_apply' → 申请单原始医嘱,应保留
|
-- based_on_table='exam_apply'/'lab_apply' → 申请单原始医嘱,应保留
|
||||||
AND (T1.based_on_id IS NULL OR T1.based_on_table IS NULL OR T1.based_on_table NOT IN ('med_medication_request', 'med_medication_dispense'))
|
AND (T1.based_on_id IS NULL OR T1.based_on_table IS NULL OR T1.based_on_table NOT IN ('med_medication_request', 'med_medication_dispense'))
|
||||||
<if test="sourceBillNo != null and sourceBillNo != ''">
|
|
||||||
AND T1.prescription_no = #{sourceBillNo}
|
|
||||||
</if>
|
|
||||||
<if test="historyFlag == '0'.toString()">
|
<if test="historyFlag == '0'.toString()">
|
||||||
AND T1.encounter_id = #{encounterId}
|
AND T1.encounter_id = #{encounterId}
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -155,7 +155,7 @@
|
|||||||
ii.performer_check_id,
|
ii.performer_check_id,
|
||||||
ii.category_code,
|
ii.category_code,
|
||||||
ii.dispense_status
|
ii.dispense_status
|
||||||
FROM (( SELECT DISTINCT T1.encounter_id,
|
FROM (( SELECT T1.encounter_id,
|
||||||
T1.tenant_id,
|
T1.tenant_id,
|
||||||
#{medMedicationRequest} AS advice_table,
|
#{medMedicationRequest} AS advice_table,
|
||||||
T1.id AS request_id,
|
T1.id AS request_id,
|
||||||
@@ -293,7 +293,7 @@
|
|||||||
T1.sort_number,
|
T1.sort_number,
|
||||||
T1.group_id )
|
T1.group_id )
|
||||||
UNION
|
UNION
|
||||||
( SELECT DISTINCT T1.encounter_id,
|
( SELECT T1.encounter_id,
|
||||||
T1.tenant_id,
|
T1.tenant_id,
|
||||||
#{worServiceRequest} AS advice_table,
|
#{worServiceRequest} AS advice_table,
|
||||||
T1.id AS request_id,
|
T1.id AS request_id,
|
||||||
|
|||||||
@@ -288,7 +288,7 @@
|
|||||||
AND T1.refund_device_id IS NULL
|
AND T1.refund_device_id IS NULL
|
||||||
ORDER BY T1.status_enum)
|
ORDER BY T1.status_enum)
|
||||||
UNION ALL
|
UNION ALL
|
||||||
(SELECT CASE WHEN T1.category_enum = 4 THEN 6 ELSE 3 END AS advice_type,
|
(SELECT CASE WHEN T1.category_enum = 4 THEN 6 ELSE COALESCE(T1.category_enum, 3) END AS advice_type,
|
||||||
T1.id AS request_id,
|
T1.id AS request_id,
|
||||||
T1.id || '-3' AS unique_key,
|
T1.id || '-3' AS unique_key,
|
||||||
T1.requester_id AS requester_id,
|
T1.requester_id AS requester_id,
|
||||||
@@ -373,4 +373,4 @@
|
|||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -161,9 +161,6 @@
|
|||||||
<if test="requestFormDto.surgeryNo != null and requestFormDto.surgeryNo != ''">
|
<if test="requestFormDto.surgeryNo != null and requestFormDto.surgeryNo != ''">
|
||||||
AND drf.prescription_no LIKE CONCAT('%', #{requestFormDto.surgeryNo}, '%')
|
AND drf.prescription_no LIKE CONCAT('%', #{requestFormDto.surgeryNo}, '%')
|
||||||
</if>
|
</if>
|
||||||
<if test="requestFormDto.typeCode != null and requestFormDto.typeCode != ''">
|
|
||||||
AND drf.type_code = #{requestFormDto.typeCode}
|
|
||||||
</if>
|
|
||||||
<if test="requestFormDto.applyTimeStart != null">
|
<if test="requestFormDto.applyTimeStart != null">
|
||||||
AND drf.create_time >= #{requestFormDto.applyTimeStart}
|
AND drf.create_time >= #{requestFormDto.applyTimeStart}
|
||||||
</if>
|
</if>
|
||||||
|
|||||||
@@ -27,9 +27,7 @@
|
|||||||
T9.payment_id,
|
T9.payment_id,
|
||||||
T9.picture_url,
|
T9.picture_url,
|
||||||
T9.birth_date,
|
T9.birth_date,
|
||||||
t9.english_name,
|
t9.english_name
|
||||||
t9.slot_id,
|
|
||||||
t9.pool_id
|
|
||||||
from (
|
from (
|
||||||
SELECT T1.tenant_id AS tenant_id,
|
SELECT T1.tenant_id AS tenant_id,
|
||||||
T1.id AS encounter_id,
|
T1.id AS encounter_id,
|
||||||
@@ -53,9 +51,7 @@
|
|||||||
T13.id AS payment_id,
|
T13.id AS payment_id,
|
||||||
ai.picture_url AS picture_url,
|
ai.picture_url AS picture_url,
|
||||||
T8.birth_date AS birth_date,
|
T8.birth_date AS birth_date,
|
||||||
tx.staff_english_name AS english_name,
|
tx.staff_english_name AS english_name
|
||||||
om_slot.slot_id AS slot_id,
|
|
||||||
om_slot.pool_id AS pool_id
|
|
||||||
FROM adm_encounter AS T1
|
FROM adm_encounter AS T1
|
||||||
LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0'
|
LEFT JOIN adm_organization AS T2 ON T1.organization_id = T2.ID AND T2.delete_flag = '0'
|
||||||
LEFT JOIN adm_healthcare_service AS T3 ON T1.service_type_id = T3.ID AND T3.delete_flag = '0'
|
LEFT JOIN adm_healthcare_service AS T3 ON T1.service_type_id = T3.ID AND T3.delete_flag = '0'
|
||||||
@@ -95,8 +91,6 @@
|
|||||||
AND T13.status_enum = ${paymentStatus}
|
AND T13.status_enum = ${paymentStatus}
|
||||||
LEFT JOIN adm_invoice AS ai
|
LEFT JOIN adm_invoice AS ai
|
||||||
ON ai.reconciliation_id = T13.id AND ai.delete_flag = '0'
|
ON ai.reconciliation_id = T13.id AND ai.delete_flag = '0'
|
||||||
LEFT JOIN order_main AS om ON T1.order_id = om.id AND om.delete_flag = '0'
|
|
||||||
LEFT JOIN adm_schedule_slot AS om_slot ON om.slot_id = om_slot.id
|
|
||||||
WHERE T1.delete_flag = '0'
|
WHERE T1.delete_flag = '0'
|
||||||
AND T1.class_enum = #{classEnum}
|
AND T1.class_enum = #{classEnum}
|
||||||
AND T10.context_enum = #{register}
|
AND T10.context_enum = #{register}
|
||||||
|
|||||||
@@ -270,10 +270,6 @@ public enum AssignSeqEnum {
|
|||||||
* 诊疗处方号
|
* 诊疗处方号
|
||||||
*/
|
*/
|
||||||
ACTIVITY_PSYCHOTROPIC_NO("62", "诊疗处方号", "PAR"),
|
ACTIVITY_PSYCHOTROPIC_NO("62", "诊疗处方号", "PAR"),
|
||||||
/**
|
|
||||||
* 检查申请单号(住院)
|
|
||||||
*/
|
|
||||||
CHECK_APPLY_NO("72", "检查申请单号", "JCZ"),
|
|
||||||
/**
|
/**
|
||||||
* b 病历文书
|
* b 病历文书
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -193,9 +193,6 @@ public class OpSchedule extends HisBaseEntity {
|
|||||||
/** 外请专家姓名 */
|
/** 外请专家姓名 */
|
||||||
private String externalExpertName;
|
private String externalExpertName;
|
||||||
|
|
||||||
/** 费用类别 */
|
|
||||||
private String feeType;
|
|
||||||
|
|
||||||
/** 备注信息 */
|
/** 备注信息 */
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS triage_queue_item (
|
|||||||
patient_name VARCHAR(255),
|
patient_name VARCHAR(255),
|
||||||
healthcare_name VARCHAR(255),
|
healthcare_name VARCHAR(255),
|
||||||
practitioner_name VARCHAR(255),
|
practitioner_name VARCHAR(255),
|
||||||
status INTEGER NOT NULL DEFAULT 0, -- 分诊队列状态: 0=WAITING(等待), 10=CALLING(叫号中), 20=IN_CLINIC(诊中), 30=COMPLETED(已完成), 40=SKIPPED(已跳过)
|
status VARCHAR(50) NOT NULL, -- WAITING/CALLING/SKIPPED/COMPLETED
|
||||||
queue_order INTEGER NOT NULL,
|
queue_order INTEGER NOT NULL,
|
||||||
create_time TIMESTAMP,
|
create_time TIMESTAMP,
|
||||||
update_time TIMESTAMP,
|
update_time TIMESTAMP,
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
-- Bug #400 修复:triage_queue_item.status 字段类型修正
|
|
||||||
-- 原 DDL 将 status 定义为 VARCHAR(50),但 Java 实体 TriageQueueItem.status 为 Integer 类型,
|
|
||||||
-- 应用层使用 TriageQueueStatus 枚举值(0/10/20/30/40)写入,类型不匹配导致 MyBatis-Plus
|
|
||||||
-- 无法正确映射 status 字段,完诊时 status 更新为 30 失败。
|
|
||||||
--
|
|
||||||
-- 注意:必须在后端实际连接的 schema 中执行(dev=hisdev, test=histest, prd=hisprd)
|
|
||||||
-- 执行前请先确认:SET search_path TO hisdev; (或对应的 schema)
|
|
||||||
|
|
||||||
-- 1. 先将已有的字符串值转换为对应的整数值
|
|
||||||
-- 如果之前写入的是枚举 code(如 'waiting'、'completed'),需要先转换
|
|
||||||
UPDATE triage_queue_item
|
|
||||||
SET status = CASE
|
|
||||||
WHEN status IN ('0', 'waiting', 'WAITING') THEN 0
|
|
||||||
WHEN status IN ('10', 'calling', 'CALLING') THEN 10
|
|
||||||
WHEN status IN ('20', 'in-clinic', 'IN_CLINIC', 'in-clinic') THEN 20
|
|
||||||
WHEN status IN ('30', 'completed', 'COMPLETED') THEN 30
|
|
||||||
WHEN status IN ('40', 'skipped', 'SKIPPED') THEN 40
|
|
||||||
WHEN status IN ('50', 'refunded', 'REFUNDED') THEN 50
|
|
||||||
WHEN status IN ('60', 'follow', 'FOLLOW') THEN 60
|
|
||||||
ELSE 0
|
|
||||||
END
|
|
||||||
WHERE status IS NOT NULL AND status !~ '^[0-9]+$';
|
|
||||||
|
|
||||||
-- 2. 修改字段类型为 INTEGER
|
|
||||||
ALTER TABLE triage_queue_item
|
|
||||||
ALTER COLUMN status TYPE INTEGER USING status::INTEGER;
|
|
||||||
|
|
||||||
-- 3. 设置默认值
|
|
||||||
ALTER TABLE triage_queue_item
|
|
||||||
ALTER COLUMN status SET DEFAULT 0;
|
|
||||||
@@ -163,7 +163,7 @@ export function updateCheckPart(data) {
|
|||||||
// 查询检查套餐列表
|
// 查询检查套餐列表
|
||||||
export function listCheckPackage(query) {
|
export function listCheckPackage(query) {
|
||||||
return request({
|
return request({
|
||||||
url: '/system/package/list',
|
url: '/system/check-package/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: query
|
params: query
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -226,14 +226,8 @@ function getList() {
|
|||||||
getDiagnosisTreatmentList(queryParams.value).then((res) => {
|
getDiagnosisTreatmentList(queryParams.value).then((res) => {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
catagoryList.value = res.data.records.map(record => {
|
catagoryList.value = res.data.records.map(record => {
|
||||||
|
// 为每一行初始化 filteredOptions,确保显示框能正确显示项目名称
|
||||||
const filteredOptions = allImplementDepartmentList.value.slice(0, 100);
|
const filteredOptions = allImplementDepartmentList.value.slice(0, 100);
|
||||||
// 确保后端返回的项目名称选项存在于 filteredOptions 中,避免 el-select 因找不到选项而回显为 ID
|
|
||||||
if (record.activityDefinitionId && !filteredOptions.some(o => o.value === record.activityDefinitionId)) {
|
|
||||||
filteredOptions.push({
|
|
||||||
value: record.activityDefinitionId,
|
|
||||||
label: record.activityDefinitionId_dictText || record.activityDefinitionId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
...record,
|
...record,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|||||||
@@ -372,6 +372,7 @@ import {
|
|||||||
} from './diagnosistreatment';
|
} from './diagnosistreatment';
|
||||||
import PopoverList from '@/components/OpenHis/popoverList/index.vue';
|
import PopoverList from '@/components/OpenHis/popoverList/index.vue';
|
||||||
import medicineList from './medicineList.vue';
|
import medicineList from './medicineList.vue';
|
||||||
|
import MedicineList from '../components/medicineList.vue';
|
||||||
import {getCurrentInstance, nextTick, watch} from 'vue';
|
import {getCurrentInstance, nextTick, watch} from 'vue';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
@@ -466,9 +467,9 @@ function calculateTotalPrice() {
|
|||||||
try {
|
try {
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
treatmentItems.value.forEach((item) => {
|
treatmentItems.value.forEach((item) => {
|
||||||
if (item.adviceDefinitionId && item.adviceDefinitionId !== '') {
|
if (item.adviceDefinitionId && item.retailPrice && item.childrenRequestNum) {
|
||||||
const price = Number(item.retailPrice) || 0;
|
const price = parseFloat(item.retailPrice) || 0;
|
||||||
const count = Number(item.childrenRequestNum) || 0;
|
const count = parseInt(item.childrenRequestNum) || 0;
|
||||||
sum += price * count;
|
sum += price * count;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -478,10 +479,7 @@ function calculateTotalPrice() {
|
|||||||
(item) => item.adviceDefinitionId && item.adviceDefinitionId !== ''
|
(item) => item.adviceDefinitionId && item.adviceDefinitionId !== ''
|
||||||
);
|
);
|
||||||
if (hasValidItem) {
|
if (hasValidItem) {
|
||||||
// 使用 nextTick 确保总价更新后零售价才更新,避免 Vue 响应式时序问题
|
form.value.retailPrice = parseFloat(totalPrice.value);
|
||||||
nextTick(() => {
|
|
||||||
form.value.retailPrice = parseFloat(totalPrice.value) || 0;
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
form.value.retailPrice = undefined;
|
form.value.retailPrice = undefined;
|
||||||
}
|
}
|
||||||
@@ -567,16 +565,15 @@ function edit() {
|
|||||||
form.value.pricingFlag = 1;
|
form.value.pricingFlag = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理子项数据,确保包含retailPrice和name字段
|
// 处理子项数据,确保包含retailPrice字段
|
||||||
if (props.item.childrenJson) {
|
if (props.item.childrenJson) {
|
||||||
const parsedItems = JSON.parse(props.item.childrenJson);
|
const parsedItems = JSON.parse(props.item.childrenJson);
|
||||||
treatmentItems.value = parsedItems.map((item) => ({
|
treatmentItems.value = parsedItems.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
name: item.name || '',
|
|
||||||
retailPrice: item.retailPrice || 0,
|
retailPrice: item.retailPrice || 0,
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, name: '', retailPrice: 0 }];
|
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, retailPrice: 0 }];
|
||||||
}
|
}
|
||||||
form.value.permittedUnitCode = form.value.permittedUnitCode
|
form.value.permittedUnitCode = form.value.permittedUnitCode
|
||||||
? form.value.permittedUnitCode.toString()
|
? form.value.permittedUnitCode.toString()
|
||||||
@@ -621,7 +618,7 @@ function reset() {
|
|||||||
chrgitmLv: undefined, //医保等级
|
chrgitmLv: undefined, //医保等级
|
||||||
pricingFlag: 1, // 划价标记,默认允许划价
|
pricingFlag: 1, // 划价标记,默认允许划价
|
||||||
};
|
};
|
||||||
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, name: '', retailPrice: 0 }];
|
treatmentItems.value = [{ adviceDefinitionId: '', childrenRequestNum: 1, retailPrice: 0 }];
|
||||||
totalPrice.value = '0.00';
|
totalPrice.value = '0.00';
|
||||||
proxy.resetForm('diagnosisTreatmentRef');
|
proxy.resetForm('diagnosisTreatmentRef');
|
||||||
}
|
}
|
||||||
@@ -763,10 +760,7 @@ function selectRow(row, index) {
|
|||||||
treatmentItems.value[index].adviceDefinitionId = row.id;
|
treatmentItems.value[index].adviceDefinitionId = row.id;
|
||||||
treatmentItems.value[index].retailPrice = row.retailPrice || 0;
|
treatmentItems.value[index].retailPrice = row.retailPrice || 0;
|
||||||
medicineSearchKey.value = '';
|
medicineSearchKey.value = '';
|
||||||
// 使用 nextTick 确保 DOM 更新后再计算总价
|
calculateTotalPrice();
|
||||||
nextTick(() => {
|
|
||||||
calculateTotalPrice();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清空诊疗子项
|
// 清空诊疗子项
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ const emit = defineEmits(['selectRow']);
|
|||||||
const diagnosisTreatmentList = ref([]); // 原始数据列表
|
const diagnosisTreatmentList = ref([]); // 原始数据列表
|
||||||
const filteredList = ref([]); // 过滤后的数据列表
|
const filteredList = ref([]); // 过滤后的数据列表
|
||||||
const hasLoaded = ref(false); // 标记是否已加载数据
|
const hasLoaded = ref(false); // 标记是否已加载数据
|
||||||
const isLoading = ref(false); // 标记是否正在加载
|
|
||||||
|
|
||||||
// 获取诊疗项目列表
|
// 获取诊疗项目列表
|
||||||
function getList() {
|
function getList() {
|
||||||
@@ -54,7 +53,7 @@ function getList() {
|
|||||||
getDiagnosisTreatmentList({ statusEnum: 2, pageSize: 1000, pageNo: 1 })
|
getDiagnosisTreatmentList({ statusEnum: 2, pageSize: 1000, pageNo: 1 })
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
diagnosisTreatmentList.value =
|
diagnosisTreatmentList.value =
|
||||||
res.data?.records?.filter((item) => item.childrenJson == null || item.childrenJson === '') || [];
|
res.data?.records?.filter((item) => item.childrenJson == null) || [];
|
||||||
filterList(); // 初始化过滤
|
filterList(); // 初始化过滤
|
||||||
hasLoaded.value = true; // 标记为已加载
|
hasLoaded.value = true; // 标记为已加载
|
||||||
})
|
})
|
||||||
@@ -63,47 +62,6 @@ function getList() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 服务端搜索(当用户输入搜索关键词时)
|
|
||||||
function searchList(searchKey) {
|
|
||||||
if (!searchKey || searchKey.trim() === '') return;
|
|
||||||
isLoading.value = true;
|
|
||||||
// 使用较大的pageSize确保搜索结果尽可能多
|
|
||||||
getDiagnosisTreatmentList({ statusEnum: 2, searchKey: searchKey.trim(), pageSize: 5000, pageNo: 1 })
|
|
||||||
.then((res) => {
|
|
||||||
diagnosisTreatmentList.value =
|
|
||||||
res.data?.records?.filter((item) => item.childrenJson == null || item.childrenJson === '') || [];
|
|
||||||
filterList();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error('搜索诊疗项目数据失败:', err);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
isLoading.value = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取预加载数据(不带搜索关键词时使用)
|
|
||||||
function loadPreloadedData() {
|
|
||||||
if (props.preloadedData && props.preloadedData.length > 0) {
|
|
||||||
diagnosisTreatmentList.value = props.preloadedData;
|
|
||||||
filterList();
|
|
||||||
hasLoaded.value = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasLoaded.value) return;
|
|
||||||
getDiagnosisTreatmentList({ statusEnum: 2, pageSize: 1000, pageNo: 1 })
|
|
||||||
.then((res) => {
|
|
||||||
diagnosisTreatmentList.value =
|
|
||||||
res.data?.records?.filter((item) => item.childrenJson == null || item.childrenJson === '') || [];
|
|
||||||
filterList();
|
|
||||||
hasLoaded.value = true;
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error('获取诊疗项目数据失败:', err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 监听shouldLoadData属性变化,仅在首次为true时加载数据
|
// 监听shouldLoadData属性变化,仅在首次为true时加载数据
|
||||||
watch(
|
watch(
|
||||||
() => props.shouldLoadData,
|
() => props.shouldLoadData,
|
||||||
@@ -128,17 +86,11 @@ watch(
|
|||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
// 监听搜索关键词变化,有搜索词时走服务端搜索,否则走本地过滤
|
// 监听搜索关键词变化,实时过滤数据
|
||||||
watch(
|
watch(
|
||||||
() => props.searchKey,
|
() => props.searchKey,
|
||||||
(newVal) => {
|
() => {
|
||||||
if (newVal && newVal.trim() !== '') {
|
filterList();
|
||||||
// 有搜索关键词,走服务端搜索
|
|
||||||
searchList(newVal);
|
|
||||||
} else {
|
|
||||||
// 搜索词为空,使用预加载数据
|
|
||||||
loadPreloadedData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -115,44 +115,22 @@ function getList() {
|
|||||||
console.log('[adviceBaseList] getList() 跳过:未选择患者');
|
console.log('[adviceBaseList] getList() 跳过:未选择患者');
|
||||||
return; // 不执行API调用
|
return; // 不执行API调用
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只有在弹窗打开时才执行查询
|
// 只有在弹窗打开时才执行查询
|
||||||
if (!props.popoverVisible) {
|
if (!props.popoverVisible) {
|
||||||
console.log('[adviceBaseList] getList() 跳过:弹窗未打开');
|
console.log('[adviceBaseList] getList() 跳过:弹窗未打开');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔧 Bug #448 修复:显式构建请求参数,确保 adviceType 正确传递
|
queryParams.value.organizationId = props.patientInfo.orgId;
|
||||||
// 不直接使用 queryParams.value,避免 undefined 值被发送到后端导致过滤失效
|
console.log('[adviceBaseList] getList() 请求参数:', JSON.stringify(queryParams.value));
|
||||||
const requestParams = {
|
|
||||||
pageSize: queryParams.value.pageSize,
|
getAdviceBaseInfo(queryParams.value).then((res) => {
|
||||||
pageNum: queryParams.value.pageNum,
|
|
||||||
organizationId: props.patientInfo.orgId,
|
|
||||||
};
|
|
||||||
|
|
||||||
// 只在 adviceType 有值时添加(0 是无效值,undefined/null 会导致后端查询所有类型)
|
|
||||||
if (queryParams.value.adviceType != null && queryParams.value.adviceType !== 0) {
|
|
||||||
requestParams.adviceType = queryParams.value.adviceType;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只在 categoryCode 有值时添加
|
|
||||||
if (queryParams.value.categoryCode) {
|
|
||||||
requestParams.categoryCode = queryParams.value.categoryCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 只在 searchKey 有值时添加
|
|
||||||
if (queryParams.value.searchKey) {
|
|
||||||
requestParams.searchKey = queryParams.value.searchKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('[adviceBaseList] getList() 请求参数:', JSON.stringify(requestParams));
|
|
||||||
|
|
||||||
getAdviceBaseInfo(requestParams).then((res) => {
|
|
||||||
console.log('[adviceBaseList] getList() 响应数据:', {
|
console.log('[adviceBaseList] getList() 响应数据:', {
|
||||||
total: res.data?.total,
|
total: res.data?.total,
|
||||||
recordsCount: res.data?.records?.length || 0,
|
recordsCount: res.data?.records?.length || 0,
|
||||||
firstRecord: res.data?.records?.[0]?.adviceName || '无数据',
|
firstRecord: res.data?.records?.[0]?.adviceName || '无数据',
|
||||||
adviceType: requestParams.adviceType
|
adviceType: queryParams.value.adviceType
|
||||||
});
|
});
|
||||||
adviceBaseList.value = res.data.records || [];
|
adviceBaseList.value = res.data.records || [];
|
||||||
total.value = res.data.total || 0;
|
total.value = res.data.total || 0;
|
||||||
|
|||||||
@@ -58,17 +58,10 @@ export function singOut(data) {
|
|||||||
/**
|
/**
|
||||||
* 获取患者本次就诊处方
|
* 获取患者本次就诊处方
|
||||||
*/
|
*/
|
||||||
export function getPrescriptionList(encounterId, generateSourceEnum, sourceBillNo) {
|
export function getPrescriptionList(encounterId) {
|
||||||
let url = '/doctor-station/advice/request-base-info?encounterId=' + encounterId
|
// Add timestamp to bypass browser caching and ensure fresh data is loaded
|
||||||
if (generateSourceEnum != null) {
|
|
||||||
url += '&generateSourceEnum=' + generateSourceEnum
|
|
||||||
}
|
|
||||||
if (sourceBillNo != null) {
|
|
||||||
url += '&sourceBillNo=' + encodeURIComponent(sourceBillNo)
|
|
||||||
}
|
|
||||||
url += '&t=' + Date.now()
|
|
||||||
return request({
|
return request({
|
||||||
url: url,
|
url: '/doctor-station/advice/request-base-info?encounterId=' + encounterId + '&t=' + Date.now(),
|
||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -381,14 +381,6 @@ const props = defineProps({
|
|||||||
activeTab: {
|
activeTab: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
generateSourceEnum: {
|
|
||||||
type: Number,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
sourceBillNo: {
|
|
||||||
type: String,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
const isAdding = ref(false);
|
const isAdding = ref(false);
|
||||||
const isSaving = ref(false); // #437 防重复提交锁
|
const isSaving = ref(false); // #437 防重复提交锁
|
||||||
@@ -476,11 +468,7 @@ watch(
|
|||||||
|
|
||||||
function getListInfo(addNewRow) {
|
function getListInfo(addNewRow) {
|
||||||
isAdding.value = false;
|
isAdding.value = false;
|
||||||
getPrescriptionList(
|
getPrescriptionList(props.patientInfo.encounterId).then((res) => {
|
||||||
props.patientInfo.encounterId,
|
|
||||||
props.generateSourceEnum ?? undefined,
|
|
||||||
props.sourceBillNo ?? undefined,
|
|
||||||
).then((res) => {
|
|
||||||
// 为每行数据添加 adviceTypeValue 字段,用于类型下拉框显示
|
// 为每行数据添加 adviceTypeValue 字段,用于类型下拉框显示
|
||||||
prescriptionList.value = (res.data || []).map(item => {
|
prescriptionList.value = (res.data || []).map(item => {
|
||||||
// 根据 adviceType 和 categoryCode 找到对应的 adviceTypeValue
|
// 根据 adviceType 和 categoryCode 找到对应的 adviceTypeValue
|
||||||
@@ -880,27 +868,19 @@ function handleDelete() {
|
|||||||
proxy.$modal.msgWarning('请选择要删除的项目');
|
proxy.$modal.msgWarning('请选择要删除的项目');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let deleteList = groupIndexList.value.map((index) => {
|
let deleteList = groupIndexList.value.map((index) => {
|
||||||
const item = prescriptionList.value[index];
|
const item = prescriptionList.value[index];
|
||||||
// 只删除待签发且未收费的项目
|
// 只删除待签发且未收费的项目
|
||||||
if (item.statusEnum != 1 || item.chargeStatus == 5) {
|
if (item.statusEnum != 1 || item.chargeStatus == 5) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// 🔧 Bug #442: 非本人创建的医嘱不允许删除(与签发/签退逻辑保持一致)
|
|
||||||
if (Number(item.bizRequestFlag) !== 1 && item.bizRequestFlag) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// 🔧 Bug #442: 已保存的行必须有有效的 requestId,否则跳过(避免后端删除不存在的记录)
|
|
||||||
if (item.requestId == null || item.requestId === undefined || item.requestId === '') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
requestId: item.requestId,
|
requestId: item.requestId,
|
||||||
dbOpType: '3',
|
dbOpType: '3',
|
||||||
adviceType: item.adviceType,
|
adviceType: item.adviceType,
|
||||||
};
|
};
|
||||||
}).filter(item => item !== null); // 过滤掉已签发、已收费、非本人创建或无 requestId 的项目
|
}).filter(item => item !== null); // 过滤掉已签发或已收费的项目
|
||||||
|
|
||||||
if (deleteList.length == 0) {
|
if (deleteList.length == 0) {
|
||||||
proxy.$modal.msgWarning('只能删除待签发且未收费的项目');
|
proxy.$modal.msgWarning('只能删除待签发且未收费的项目');
|
||||||
@@ -1036,14 +1016,6 @@ function handleSave() {
|
|||||||
requestId: item.requestId,
|
requestId: item.requestId,
|
||||||
dbOpType: '1',
|
dbOpType: '1',
|
||||||
groupId: item.groupId,
|
groupId: item.groupId,
|
||||||
// 🔧 Bug #443: 补充顶层关键字段(这些不在 contentJson 中,需从 API 响应顶层提取)
|
|
||||||
encounterId: item.encounterId,
|
|
||||||
patientId: item.patientId,
|
|
||||||
locationId: item.positionId,
|
|
||||||
adviceType: item.adviceType,
|
|
||||||
adviceTableName: item.adviceTableName,
|
|
||||||
adviceDefinitionId: item.adviceDefinitionId,
|
|
||||||
chargeItemId: item.chargeItemId,
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
savePrescriptionSign({
|
savePrescriptionSign({
|
||||||
|
|||||||
@@ -1243,14 +1243,11 @@ async function show(diagnosisData) {
|
|||||||
const res = await getNextCardNo(orgCode);
|
const res = await getNextCardNo(orgCode);
|
||||||
if (res.code === 200 && res.data && res.data.length >= 12) {
|
if (res.code === 200 && res.data && res.data.length >= 12) {
|
||||||
cardNo = res.data;
|
cardNo = res.data;
|
||||||
} else {
|
|
||||||
// API返回失败或不合规时,生成临时卡号避免保存时 cardNo 为空导致后端校验失败
|
|
||||||
cardNo = 'TEMP_' + Date.now();
|
|
||||||
}
|
}
|
||||||
|
// API失败或返回不合规时保持为空字符串,由用户手动填写或后端自动生成
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('获取卡片编号失败:', err);
|
console.error('获取卡片编号失败:', err);
|
||||||
// API调用异常时,生成临时卡号
|
// 保持为空,不使用不合规的临时值
|
||||||
cardNo = 'TEMP_' + Date.now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
form.value = {
|
form.value = {
|
||||||
@@ -1366,9 +1363,6 @@ async function buildSubmitData() {
|
|||||||
} else if (formData.otherDisease) {
|
} else if (formData.otherDisease) {
|
||||||
// 其他传染病使用自定义编码
|
// 其他传染病使用自定义编码
|
||||||
diseaseCode = 'OTHER';
|
diseaseCode = 'OTHER';
|
||||||
} else if (formData.selectedDiseases && formData.selectedDiseases.length > 0) {
|
|
||||||
// 兜底:如果 ClassA/B/C 都为空但 selectedDiseases 有值,取第一个作为 diseaseCode
|
|
||||||
diseaseCode = formData.selectedDiseases[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换年龄单位:岁=1, 月=2, 天=3
|
// 转换年龄单位:岁=1, 月=2, 天=3
|
||||||
@@ -1436,8 +1430,8 @@ async function buildSubmitData() {
|
|||||||
function validateFormManually() {
|
function validateFormManually() {
|
||||||
const errors = [];
|
const errors = [];
|
||||||
|
|
||||||
// 卡片编号验证(至少12位,后端自动生成16位编号;临时卡号 TEMP_ 开头允许通过)
|
// 卡片编号验证(至少12位,后端自动生成16位编号)
|
||||||
if (form.value.cardNo && !form.value.cardNo.startsWith('TEMP_') && form.value.cardNo.length < 12) {
|
if (form.value.cardNo && form.value.cardNo.length < 12) {
|
||||||
errors.push('卡片编号至少12位');
|
errors.push('卡片编号至少12位');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1778,33 +1772,6 @@ defineExpose({ show, showReport, close: handleClose });
|
|||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 输入框下划线样式(与 underline-select 保持一致) */
|
|
||||||
.underline-input :deep(.el-input__wrapper) {
|
|
||||||
border: none;
|
|
||||||
border-bottom: 1px solid #dcdfe6;
|
|
||||||
border-radius: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.underline-input :deep(.el-input__wrapper:hover) {
|
|
||||||
border-bottom-color: #c0c4cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.underline-input :deep(.el-input__wrapper.is-focus) {
|
|
||||||
border-bottom-color: #409eff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.underline-input :deep(.el-input__inner) {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.underline-input :deep(.el-input__inner::placeholder) {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 街道下拉框下划线样式 */
|
/* 街道下拉框下划线样式 */
|
||||||
.underline-select {
|
.underline-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -3,56 +3,15 @@
|
|||||||
<!-- ====== 顶部卡片:申请单列表 ====== -->
|
<!-- ====== 顶部卡片:申请单列表 ====== -->
|
||||||
<div class="top-section">
|
<div class="top-section">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
<span class="section-title">检查项目 ({{ filteredApplicationList.length }})</span>
|
<span class="section-title">检查项目 ({{ applicationList.length }})</span>
|
||||||
<div class="header-actions">
|
<div class="header-actions">
|
||||||
<el-button type="primary" @click="handleAdd" icon="Plus">新增</el-button>
|
<el-button type="primary" @click="handleAdd" icon="Plus">新增</el-button>
|
||||||
<el-button type="success" @click="handleSave" icon="Finished">保存</el-button>
|
<el-button type="success" @click="handleSave" icon="Finished">保存</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Bug #499: 查询过滤工具栏 -->
|
|
||||||
<div class="search-toolbar">
|
|
||||||
<el-form :inline="true" size="small">
|
|
||||||
<el-form-item label="日期范围">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="searchForm.dateRange"
|
|
||||||
type="daterange"
|
|
||||||
range-separator="至"
|
|
||||||
start-placeholder="开始日期"
|
|
||||||
end-placeholder="结束日期"
|
|
||||||
value-format="YYYY-MM-DD"
|
|
||||||
style="width: 240px"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="状态">
|
|
||||||
<el-select v-model="searchForm.applyStatus" placeholder="全部" clearable style="width: 140px">
|
|
||||||
<el-option
|
|
||||||
v-for="opt in statusOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="关键字">
|
|
||||||
<el-input
|
|
||||||
v-model="searchForm.keyword"
|
|
||||||
placeholder="申请单号 / 检查项目"
|
|
||||||
clearable
|
|
||||||
style="width: 200px"
|
|
||||||
@keyup.enter="handleSearch"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="handleSearch" icon="Search">搜索</el-button>
|
|
||||||
<el-button @click="handleResetSearch" icon="Refresh">重置</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-table
|
<el-table
|
||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:data="filteredApplicationList"
|
:data="applicationList"
|
||||||
:max-height="200"
|
:max-height="200"
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
@row-click="handleRowClick"
|
@row-click="handleRowClick"
|
||||||
@@ -376,9 +335,8 @@
|
|||||||
加载中...
|
加载中...
|
||||||
</div>
|
</div>
|
||||||
<!-- Bug #428修复: 渲染分类联动加载的检查方法列表 -->
|
<!-- Bug #428修复: 渲染分类联动加载的检查方法列表 -->
|
||||||
<!-- Bug #500修复: v-if 改为 v-show,避免方法列表加载时 DOM 突然插入导致高度跳变 -->
|
|
||||||
<div
|
<div
|
||||||
v-show="cat.methods && cat.methods.length > 0"
|
v-if="cat.methods && cat.methods.length > 0"
|
||||||
class="method-section"
|
class="method-section"
|
||||||
>
|
>
|
||||||
<div class="method-section-title">检查方法</div>
|
<div class="method-section-title">检查方法</div>
|
||||||
@@ -444,21 +402,6 @@
|
|||||||
<span class="method-price">¥{{ method.packagePrice || item.price }}</span>
|
<span class="method-price">¥{{ method.packagePrice || item.price }}</span>
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</div>
|
</div>
|
||||||
<!-- 选中方法后,显示对应的套餐明细 -->
|
|
||||||
<div v-if="item.selectedMethod && item.methodPackageDetails && item.methodPackageDetails.length > 0" class="method-package-details">
|
|
||||||
<div class="method-package-header">
|
|
||||||
<span class="method-package-title">套餐明细 - {{ item.selectedMethod.name }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-for="detail in item.methodPackageDetails" :key="detail.id" class="method-option">
|
|
||||||
<el-checkbox v-model="detail.checked">
|
|
||||||
<span class="method-name">{{ detail.name }}</span>
|
|
||||||
<span class="method-price">数量: {{ detail.quantity }} ¥{{ detail.price }}</span>
|
|
||||||
</el-checkbox>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="item.selectedMethod && item.methodPackageLoading" class="method-package-loading">
|
|
||||||
加载套餐明细中...
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -476,7 +419,7 @@ import { ElMessage, ElMessageBox } from 'element-plus';
|
|||||||
import { Printer, Delete, ArrowDown, ArrowUp, Close } from '@element-plus/icons-vue';
|
import { Printer, Delete, ArrowDown, ArrowUp, Close } from '@element-plus/icons-vue';
|
||||||
import useUserStore from '@/store/modules/user';
|
import useUserStore from '@/store/modules/user';
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
import { listCheckMethod, searchCheckMethod, listCheckPackage } from '@/api/system/checkType';
|
import { listCheckMethod, searchCheckMethod } from '@/api/system/checkType';
|
||||||
import { getEncounterDiagnosis } from '../api.js';
|
import { getEncounterDiagnosis } from '../api.js';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -494,74 +437,6 @@ const activeDetailTab = ref('applyForm');
|
|||||||
const applicationList = ref([]);
|
const applicationList = ref([]);
|
||||||
const selectedItems = ref([]);
|
const selectedItems = ref([]);
|
||||||
|
|
||||||
// Bug #499: 查询过滤状态
|
|
||||||
const searchForm = reactive({
|
|
||||||
dateRange: [],
|
|
||||||
applyStatus: '',
|
|
||||||
keyword: ''
|
|
||||||
});
|
|
||||||
|
|
||||||
// 申请单状态选项
|
|
||||||
const statusOptions = [
|
|
||||||
{ label: '已开单', value: 0 },
|
|
||||||
{ label: '已收费', value: 1 },
|
|
||||||
{ label: '已预约', value: 2 },
|
|
||||||
{ label: '已签到', value: 3 },
|
|
||||||
{ label: '部分报告', value: 4 },
|
|
||||||
{ label: '已完告', value: 5 },
|
|
||||||
{ label: '已作废', value: 6 }
|
|
||||||
];
|
|
||||||
|
|
||||||
// Bug #499: 过滤后的申请单列表
|
|
||||||
const filteredApplicationList = computed(() => {
|
|
||||||
let result = applicationList.value;
|
|
||||||
|
|
||||||
// 日期范围过滤
|
|
||||||
if (searchForm.dateRange && searchForm.dateRange.length === 2) {
|
|
||||||
const start = searchForm.dateRange[0];
|
|
||||||
const end = searchForm.dateRange[1];
|
|
||||||
result = result.filter(item => {
|
|
||||||
const d = item.applyTime;
|
|
||||||
if (!d) return false;
|
|
||||||
const dateStr = d.length > 10 ? d.substring(0, 10) : d;
|
|
||||||
return dateStr >= start && dateStr <= end;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 状态过滤
|
|
||||||
if (searchForm.applyStatus !== '' && searchForm.applyStatus !== null && searchForm.applyStatus !== undefined) {
|
|
||||||
result = result.filter(item => item.applyStatus === searchForm.applyStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关键字过滤(申请单号、申检部位、检查项目名)
|
|
||||||
if (searchForm.keyword) {
|
|
||||||
const kw = searchForm.keyword.toLowerCase();
|
|
||||||
result = result.filter(item => {
|
|
||||||
return (item.applyNo || '').toLowerCase().includes(kw)
|
|
||||||
|| (item.inspectionArea || '').toLowerCase().includes(kw);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Bug #499: 搜索与重置
|
|
||||||
function handleSearch() {
|
|
||||||
// 过滤逻辑由 computed 自动处理
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleResetSearch() {
|
|
||||||
const now = new Date();
|
|
||||||
const end = now.toISOString().substring(0, 10);
|
|
||||||
const start = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000).toISOString().substring(0, 10);
|
|
||||||
searchForm.dateRange = [start, end];
|
|
||||||
searchForm.applyStatus = '';
|
|
||||||
searchForm.keyword = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化默认日期范围为近一周
|
|
||||||
handleResetSearch();
|
|
||||||
|
|
||||||
// 🔧 BugFix#426: 懒加载套餐明细
|
// 🔧 BugFix#426: 懒加载套餐明细
|
||||||
async function loadPackageDetails(row, treeNode, resolve) {
|
async function loadPackageDetails(row, treeNode, resolve) {
|
||||||
if (!row.isPackage || !row.packageId) {
|
if (!row.isPackage || !row.packageId) {
|
||||||
@@ -570,7 +445,7 @@ async function loadPackageDetails(row, treeNode, resolve) {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url: `/system/package/${row.packageId}/details`,
|
url: `/exam/package/${row.packageId}/details`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
@@ -592,28 +467,14 @@ async function loadPackageDetails(row, treeNode, resolve) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// #428修复: 为已选择项目加载套餐明细(通过packageId或packageName查询)
|
// #428: 为已选择项目加载套餐明细
|
||||||
async function loadPackageDetailsForItem(item) {
|
async function loadPackageDetailsForItem(item) {
|
||||||
if (!item.isPackage || (!item.packageId && !item.packageName)) {
|
if (!item.isPackage || !item.packageId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let packageId = item.packageId;
|
|
||||||
if (!packageId && item.packageName) {
|
|
||||||
// CheckPart 没有 packageId 字段,需要通过 packageName 查询获取
|
|
||||||
const pkgRes = await listCheckPackage({ packageName: item.packageName });
|
|
||||||
let packages = pkgRes?.data || [];
|
|
||||||
if (!Array.isArray(packages)) {
|
|
||||||
packages = packages.records || packages.data || [];
|
|
||||||
}
|
|
||||||
if (packages.length === 0) {
|
|
||||||
item.packageDetails = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
packageId = packages[0].id;
|
|
||||||
}
|
|
||||||
const res = await request({
|
const res = await request({
|
||||||
url: `/system/package/${packageId}/details`,
|
url: `/exam/package/${item.packageId}/details`,
|
||||||
method: 'get'
|
method: 'get'
|
||||||
});
|
});
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
@@ -621,7 +482,7 @@ async function loadPackageDetailsForItem(item) {
|
|||||||
...detail,
|
...detail,
|
||||||
name: detail.name || detail.itemName,
|
name: detail.name || detail.itemName,
|
||||||
unit: detail.unit || '次',
|
unit: detail.unit || '次',
|
||||||
price: detail.price || detail.unitPrice || 0,
|
price: detail.price || detail.itemPrice || 0,
|
||||||
quantity: detail.quantity || 1
|
quantity: detail.quantity || 1
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
@@ -683,7 +544,6 @@ const categoryList = ref([]); // 原始分类+项目数据
|
|||||||
const dictSearchKey = ref('');
|
const dictSearchKey = ref('');
|
||||||
const activeNames = ref(''); // 当前展开的折叠项
|
const activeNames = ref(''); // 当前展开的折叠项
|
||||||
const categoryLoadingSet = ref(new Set()); // Bug #500: 正在加载方法的分类集合
|
const categoryLoadingSet = ref(new Set()); // Bug #500: 正在加载方法的分类集合
|
||||||
const currentActiveCategory = ref(null); // Bug #500: 记录当前激活的分类,忽略过期请求响应
|
|
||||||
const isAnimating = ref(false); // Bug #500: 防止快速切换时折叠动画重叠导致抖动
|
const isAnimating = ref(false); // Bug #500: 防止快速切换时折叠动画重叠导致抖动
|
||||||
|
|
||||||
const allMethods = ref([]);
|
const allMethods = ref([]);
|
||||||
@@ -801,18 +661,15 @@ const availableMethods = computed(() => {
|
|||||||
// 当可选方法列表改变时,如果当前选中的方法不在新列表中,则清空
|
// 当可选方法列表改变时,如果当前选中的方法不在新列表中,则清空
|
||||||
// #428: 分类展开时联动加载检查方法
|
// #428: 分类展开时联动加载检查方法
|
||||||
// Bug #500: 使用 categoryLoadingSet 替代 dictLoading,避免切换分类时整个区域闪烁
|
// Bug #500: 使用 categoryLoadingSet 替代 dictLoading,避免切换分类时整个区域闪烁
|
||||||
// Bug #500: 添加 currentActiveCategory 守卫,忽略过期请求响应,防止快速切换时数据闪烁
|
|
||||||
async function handleCategoryExpand(cat) {
|
async function handleCategoryExpand(cat) {
|
||||||
if (!cat || !cat.typeName) return;
|
if (!cat || !cat.typeName) return;
|
||||||
|
|
||||||
|
// 如果已加载过或正在加载中,跳过
|
||||||
if ((cat.methods && cat.methods.length > 0) || categoryLoadingSet.value.has(cat.typeId)) return;
|
if ((cat.methods && cat.methods.length > 0) || categoryLoadingSet.value.has(cat.typeId)) return;
|
||||||
|
|
||||||
categoryLoadingSet.value.add(cat.typeId);
|
categoryLoadingSet.value.add(cat.typeId);
|
||||||
currentActiveCategory.value = cat.typeId;
|
|
||||||
try {
|
try {
|
||||||
const res = await searchCheckMethod({ checkType: cat.typeName });
|
const res = await searchCheckMethod({ checkType: cat.typeName });
|
||||||
// 忽略过期请求:用户已切换到其他分类,丢弃当前响应
|
|
||||||
if (currentActiveCategory.value !== cat.typeId) return;
|
|
||||||
let data = res?.data?.data || res?.data || res?.rows || res;
|
let data = res?.data?.data || res?.data || res?.rows || res;
|
||||||
if (!Array.isArray(data) && res?.data && Array.isArray(res.data.data)) {
|
if (!Array.isArray(data) && res?.data && Array.isArray(res.data.data)) {
|
||||||
data = res.data.data;
|
data = res.data.data;
|
||||||
@@ -825,32 +682,25 @@ async function handleCategoryExpand(cat) {
|
|||||||
code: m.code,
|
code: m.code,
|
||||||
price: m.price || 0,
|
price: m.price || 0,
|
||||||
packageName: m.packageName || '',
|
packageName: m.packageName || '',
|
||||||
packageId: m.packageId || null,
|
|
||||||
packagePrice: m.packagePrice || null,
|
packagePrice: m.packagePrice || null,
|
||||||
serviceFee: m.serviceFee || null
|
serviceFee: m.serviceFee || null
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (currentActiveCategory.value !== cat.typeId) return;
|
|
||||||
console.error('加载分类检查方法失败', err);
|
console.error('加载分类检查方法失败', err);
|
||||||
} finally {
|
} finally {
|
||||||
categoryLoadingSet.value.delete(cat.typeId);
|
categoryLoadingSet.value.delete(cat.typeId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Bug #500修复: 添加防抖逻辑,快速切换时跳过中间状态的动画,避免高度跳变和白屏闪烁
|
// Bug #500: 添加防抖逻辑,快速切换时跳过中间状态的动画,避免高度跳变和白屏闪烁
|
||||||
function handleCollapseChange(activeName) {
|
function handleCollapseChange(activeName) {
|
||||||
if (isAnimating.value) return; // 动画进行中,忽略后续点击
|
if (isAnimating.value) return; // 动画进行中,忽略后续点击
|
||||||
|
|
||||||
isAnimating.value = true;
|
isAnimating.value = true;
|
||||||
setTimeout(() => { isAnimating.value = false; }, 300); // 与 CSS 过渡时长一致
|
setTimeout(() => { isAnimating.value = false; }, 300); // 与 CSS 过渡时长一致
|
||||||
|
|
||||||
// Bug #500修复: 记录当前激活的分类,用于 handleCategoryExpand 中忽略过期请求
|
|
||||||
currentActiveCategory.value = activeName || null;
|
|
||||||
|
|
||||||
if (activeName) {
|
if (activeName) {
|
||||||
// Bug #428修复: 直接从 categoryList(原始响应式数组)查找分类,
|
const cat = filteredCategoryList.value.find(c => c.typeId == activeName);
|
||||||
// 确保后续 handleCategoryExpand 对 cat.methods 的赋值能正确触发 Vue 响应式更新
|
|
||||||
const cat = categoryList.value.find(c => c.typeId == activeName);
|
|
||||||
if (cat && (!cat.methods || cat.methods.length === 0)) {
|
if (cat && (!cat.methods || cat.methods.length === 0)) {
|
||||||
handleCategoryExpand(cat); // 异步加载,不 await
|
handleCategoryExpand(cat); // 异步加载,不 await
|
||||||
}
|
}
|
||||||
@@ -1142,20 +992,12 @@ function handleRowClick(row) {
|
|||||||
selectedItems.value = [];
|
selectedItems.value = [];
|
||||||
activeDetailTab.value = 'applyForm';
|
activeDetailTab.value = 'applyForm';
|
||||||
request({ url: `/exam/apply/${row.applyNo}`, method: 'get' }).then(async res => {
|
request({ url: `/exam/apply/${row.applyNo}`, method: 'get' }).then(async res => {
|
||||||
const resp = res.data || res;
|
const d = res.data || res;
|
||||||
// Bug #408修复: items 在 AjaxResult 顶层(res.items / resp.items),不在 ExamApply 对象内
|
if (d.data) Object.assign(form, d.data);
|
||||||
// 防御性提取:优先取顶层 items,兼容嵌套在 resp.data.items 的情况
|
if (d.items && Array.isArray(d.items)) {
|
||||||
let rawItems = res.items || resp.items;
|
|
||||||
if (!rawItems && resp.data && typeof resp.data === 'object') {
|
|
||||||
rawItems = resp.data.items;
|
|
||||||
}
|
|
||||||
rawItems = rawItems || [];
|
|
||||||
const d = resp.data || resp;
|
|
||||||
if (d) Object.assign(form, d);
|
|
||||||
if (Array.isArray(rawItems) && rawItems.length > 0) {
|
|
||||||
try {
|
try {
|
||||||
// 为每个项目加载检查方法
|
// 为每个项目加载检查方法
|
||||||
const itemsWithMethods = await Promise.all(rawItems.map(async m => {
|
const itemsWithMethods = await Promise.all(d.items.map(async m => {
|
||||||
const item = {
|
const item = {
|
||||||
id: m.itemCode, name: m.itemName,
|
id: m.itemCode, name: m.itemName,
|
||||||
price: m.itemFee || 0, quantity: 1,
|
price: m.itemFee || 0, quantity: 1,
|
||||||
@@ -1183,18 +1025,12 @@ function handleRowClick(row) {
|
|||||||
code: md.code,
|
code: md.code,
|
||||||
price: m.itemFee || 0, // fallback 到已保存的价格
|
price: m.itemFee || 0, // fallback 到已保存的价格
|
||||||
packageName: md.packageName || '',
|
packageName: md.packageName || '',
|
||||||
packageId: md.packageId || null,
|
|
||||||
packagePrice: md.packagePrice || null, // Bug #384修复: 套餐价格
|
packagePrice: md.packagePrice || null, // Bug #384修复: 套餐价格
|
||||||
serviceFee: md.serviceFee || null
|
serviceFee: md.serviceFee || null
|
||||||
}));
|
}));
|
||||||
// 如果有已保存的检查方法信息,尝试匹配
|
// 如果有已保存的检查方法信息,尝试匹配
|
||||||
if (m.checkMethodId) {
|
if (m.checkMethodId) {
|
||||||
item.selectedMethod = item.methods.find(md => md.id === m.checkMethodId) || null;
|
item.selectedMethod = item.methods.find(md => md.id === m.checkMethodId) || null;
|
||||||
// 从已保存的方法中获取套餐信息
|
|
||||||
if (item.selectedMethod?.packageId) {
|
|
||||||
item.isPackage = true;
|
|
||||||
item.packageId = item.selectedMethod.packageId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1255,13 +1091,6 @@ async function handleMethodSelect(checked, method, cat) {
|
|||||||
const existingItem = selectedItems.value.find(s => s.id === targetItem.id);
|
const existingItem = selectedItems.value.find(s => s.id === targetItem.id);
|
||||||
if (existingItem) {
|
if (existingItem) {
|
||||||
existingItem.selectedMethod = method;
|
existingItem.selectedMethod = method;
|
||||||
// 从方法中获取套餐信息
|
|
||||||
if (method.packageId) {
|
|
||||||
existingItem.isPackage = true;
|
|
||||||
existingItem.packageId = method.packageId;
|
|
||||||
// 预加载套餐明细
|
|
||||||
loadPackageDetailsForItem(existingItem);
|
|
||||||
}
|
|
||||||
updateMethodDisplay();
|
updateMethodDisplay();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1269,15 +1098,14 @@ async function handleMethodSelect(checked, method, cat) {
|
|||||||
// 如果该项目不存在,创建一个并关联方法
|
// 如果该项目不存在,创建一个并关联方法
|
||||||
if (selectedItems.value.length > 0) {
|
if (selectedItems.value.length > 0) {
|
||||||
const currentCategory = selectedItems.value[0].checkType;
|
const currentCategory = selectedItems.value[0].checkType;
|
||||||
// Bug #428修复: 使用 cat.typeName 进行比较(与 newItem.checkType 保持一致)
|
const newCategory = cat.typeCode || '';
|
||||||
const newCategory = cat.typeName || '';
|
|
||||||
if (currentCategory !== newCategory) {
|
if (currentCategory !== newCategory) {
|
||||||
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const newItem = {
|
selectedItems.value.push({
|
||||||
id: targetItem.id, name: targetItem.name,
|
id: targetItem.id, name: targetItem.name,
|
||||||
price: targetItem.price, quantity: 1,
|
price: targetItem.price, quantity: 1,
|
||||||
serviceFee: targetItem.serviceFee || 0,
|
serviceFee: targetItem.serviceFee || 0,
|
||||||
@@ -1289,16 +1117,9 @@ async function handleMethodSelect(checked, method, cat) {
|
|||||||
methods: [method],
|
methods: [method],
|
||||||
selectedMethod: method,
|
selectedMethod: method,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
// 从方法中获取套餐信息(优先级高于项目本身的 packageName)
|
isPackage: !!targetItem.packageName,
|
||||||
isPackage: !!method.packageId || !!targetItem.packageName,
|
packageId: targetItem.packageId || null
|
||||||
packageId: method.packageId || targetItem.packageId || null
|
});
|
||||||
};
|
|
||||||
selectedItems.value.push(newItem);
|
|
||||||
|
|
||||||
// 如果是套餐,预加载套餐明细
|
|
||||||
if (newItem.isPackage && newItem.packageId) {
|
|
||||||
loadPackageDetailsForItem(newItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 自动回填执行科室
|
// 自动回填执行科室
|
||||||
if (selectedItems.value.length === 1 && cat?.performDeptName) {
|
if (selectedItems.value.length === 1 && cat?.performDeptName) {
|
||||||
@@ -1343,7 +1164,6 @@ async function handleItemSelect(checked, item, cat) {
|
|||||||
code: m.code,
|
code: m.code,
|
||||||
price: m.price || item.price, // fallback 到项目价格
|
price: m.price || item.price, // fallback 到项目价格
|
||||||
packageName: m.packageName || '',
|
packageName: m.packageName || '',
|
||||||
packageId: m.packageId || null,
|
|
||||||
packagePrice: m.packagePrice || null, // Bug #384修复: 套餐价格
|
packagePrice: m.packagePrice || null, // Bug #384修复: 套餐价格
|
||||||
serviceFee: m.serviceFee || null // Bug #384修复: 服务费
|
serviceFee: m.serviceFee || null // Bug #384修复: 服务费
|
||||||
}));
|
}));
|
||||||
@@ -1355,8 +1175,7 @@ async function handleItemSelect(checked, item, cat) {
|
|||||||
|
|
||||||
if (selectedItems.value.length > 0) {
|
if (selectedItems.value.length > 0) {
|
||||||
const currentCategory = selectedItems.value[0].checkType;
|
const currentCategory = selectedItems.value[0].checkType;
|
||||||
// Bug #428修复: 使用 cat.typeName 进行比较(与 effectiveCheckType 保持一致)
|
const newCategory = cat.typeCode || '';
|
||||||
const newCategory = cat.typeName || '';
|
|
||||||
if (currentCategory !== newCategory) {
|
if (currentCategory !== newCategory) {
|
||||||
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
||||||
item.checked = false;
|
item.checked = false;
|
||||||
@@ -1377,7 +1196,6 @@ async function handleItemSelect(checked, item, cat) {
|
|||||||
selectedMethod: null,
|
selectedMethod: null,
|
||||||
expanded: false, // Bug #384修复: 新增展开状态,默认不展开
|
expanded: false, // Bug #384修复: 新增展开状态,默认不展开
|
||||||
isPackage: !!item.packageName, // Bug #428修复: 标记是否为套餐
|
isPackage: !!item.packageName, // Bug #428修复: 标记是否为套餐
|
||||||
packageName: item.packageName || null, // Bug #426修复: 套餐名称,用于查找packageId
|
|
||||||
packageId: item.packageId || null // Bug #428修复: 套餐ID
|
packageId: item.packageId || null // Bug #428修复: 套餐ID
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1410,68 +1228,21 @@ async function toggleItemExpand(item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bug #384修复: 勾选框选择检查方法(单选逻辑)
|
// Bug #384修复: 勾选框选择检查方法(单选逻辑)
|
||||||
async function selectMethodCheckbox(checked, item, method) {
|
function selectMethodCheckbox(checked, item, method) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
item.selectedMethod = method;
|
item.selectedMethod = method;
|
||||||
// 动态加载该方法对应的套餐明细
|
|
||||||
await loadMethodPackageDetails(item, method);
|
|
||||||
} else {
|
} else {
|
||||||
item.selectedMethod = null;
|
item.selectedMethod = null;
|
||||||
item.methodPackageDetails = [];
|
|
||||||
}
|
}
|
||||||
// 联动更新表单检查方法显示字段
|
// 联动更新表单检查方法显示字段
|
||||||
updateMethodDisplay();
|
updateMethodDisplay();
|
||||||
|
|
||||||
// #430: 套餐金额实时同步到申请单
|
// #430: 套餐金额实时同步到申请单
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
form.totalAmount = totalAmountCalc.value;
|
form.totalAmount = totalAmountCalc.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据检查方法的packageName加载对应的套餐明细
|
|
||||||
async function loadMethodPackageDetails(item, method) {
|
|
||||||
item.methodPackageLoading = true;
|
|
||||||
item.methodPackageDetails = [];
|
|
||||||
try {
|
|
||||||
if (!method.packageName) {
|
|
||||||
item.methodPackageLoading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 通过packageName查询套餐获取packageId
|
|
||||||
const pkgRes = await listCheckPackage({ packageName: method.packageName });
|
|
||||||
let packages = pkgRes?.data || [];
|
|
||||||
if (!Array.isArray(packages)) {
|
|
||||||
packages = packages.records || packages.data || [];
|
|
||||||
}
|
|
||||||
if (packages.length === 0) {
|
|
||||||
item.methodPackageLoading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const packageId = packages[0].id;
|
|
||||||
// 查询套餐明细
|
|
||||||
const detailRes = await request({
|
|
||||||
url: `/system/package/${packageId}/details`,
|
|
||||||
method: 'get'
|
|
||||||
});
|
|
||||||
if (detailRes.code === 200 && detailRes.data) {
|
|
||||||
item.methodPackageDetails = detailRes.data.map(d => ({
|
|
||||||
id: d.id,
|
|
||||||
name: d.itemName || d.name,
|
|
||||||
quantity: d.quantity || 1,
|
|
||||||
unit: d.unit || '次',
|
|
||||||
price: d.unitPrice || d.price || 0,
|
|
||||||
amount: d.amount || d.total || 0,
|
|
||||||
checked: true // 默认勾选
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error('加载方法套餐明细失败:', err);
|
|
||||||
item.methodPackageDetails = [];
|
|
||||||
} finally {
|
|
||||||
item.methodPackageLoading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bug #384修复: 更新检查方法显示字段(联动)
|
// Bug #384修复: 更新检查方法显示字段(联动)
|
||||||
function updateMethodDisplay() {
|
function updateMethodDisplay() {
|
||||||
// 找到第一个有选中检查方法的项目
|
// 找到第一个有选中检查方法的项目
|
||||||
@@ -1561,19 +1332,6 @@ defineExpose({ getList });
|
|||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bug #499: 查询过滤工具栏 */
|
|
||||||
.search-toolbar {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding: 8px 0;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
}
|
|
||||||
.search-toolbar :deep(.el-form-item) {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
.search-toolbar :deep(.el-form-item__label) {
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 底部区域:左表单 + 右分类 */
|
/* 底部区域:左表单 + 右分类 */
|
||||||
.bottom-section {
|
.bottom-section {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1651,7 +1409,6 @@ defineExpose({ getList });
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden; /* Bug #500: 防止切换时水平方向溢出导致抖动 */
|
overflow-x: hidden; /* Bug #500: 防止切换时水平方向溢出导致抖动 */
|
||||||
min-height: 120px; /* Bug #500: 固定最小高度,避免分类切换时 flex 容器高度突变 */
|
|
||||||
}
|
}
|
||||||
.empty-hint {
|
.empty-hint {
|
||||||
color: #909399;
|
color: #909399;
|
||||||
@@ -1891,29 +1648,6 @@ defineExpose({ getList });
|
|||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 选中方法后显示的套餐明细 */
|
|
||||||
.method-package-details {
|
|
||||||
margin-top: 4px;
|
|
||||||
padding: 4px 0;
|
|
||||||
border-top: 1px dashed #dcdfe6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-package-header {
|
|
||||||
padding: 2px 0 4px 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-package-title {
|
|
||||||
font-size: 10px;
|
|
||||||
color: #909399;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.method-package-loading {
|
|
||||||
padding: 4px 0 4px 24px;
|
|
||||||
font-size: 10px;
|
|
||||||
color: #c0c4cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 折叠组件细节 */
|
/* 折叠组件细节 */
|
||||||
:deep(.el-collapse) {
|
:deep(.el-collapse) {
|
||||||
border: none;
|
border: none;
|
||||||
@@ -1924,10 +1658,10 @@ defineExpose({ getList });
|
|||||||
height: auto;
|
height: auto;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
/* Bug #500修复: 折叠内容使用明确属性过渡,避免 transition: all 导致子元素意外动画 */
|
/* Bug #500: 折叠内容添加平滑过渡动画,避免切换时高度跳变 */
|
||||||
:deep(.el-collapse-item__content) {
|
:deep(.el-collapse-item__content) {
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
transition: height 0.3s ease, max-height 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
/* Bug #500: 折叠面板动画容器,添加 overflow:hidden 防止展开时内容溢出导致闪烁 */
|
/* Bug #500: 折叠面板动画容器,添加 overflow:hidden 防止展开时内容溢出导致闪烁 */
|
||||||
:deep(.el-collapse-item__wrap) {
|
:deep(.el-collapse-item__wrap) {
|
||||||
|
|||||||
@@ -589,46 +589,36 @@ function handleUseOrderGroup(row) {
|
|||||||
minUnitPrice: orderDetail.minUnitPrice,
|
minUnitPrice: orderDetail.minUnitPrice,
|
||||||
inventoryList: orderDetail.inventoryList || [],
|
inventoryList: orderDetail.inventoryList || [],
|
||||||
priceList: orderDetail.priceList || [],
|
priceList: orderDetail.priceList || [],
|
||||||
partPercent: orderDetail.partPercent ?? 1,
|
partPercent: orderDetail.partPercent || 1,
|
||||||
partAttributeEnum: orderDetail.partAttributeEnum,
|
|
||||||
unitConversionRatio: orderDetail.unitConversionRatio,
|
|
||||||
// 🔧 Bug #218 修复:positionId 可能存储在 item 本身,优先使用 item.positionId
|
// 🔧 Bug #218 修复:positionId 可能存储在 item 本身,优先使用 item.positionId
|
||||||
positionId: item.positionId ?? orderDetail.positionId,
|
positionId: item.positionId || orderDetail.positionId,
|
||||||
defaultLotNumber: orderDetail.defaultLotNumber,
|
defaultLotNumber: orderDetail.defaultLotNumber,
|
||||||
|
|
||||||
// 单位信息
|
// 单位信息
|
||||||
unitCode: item.unitCode ?? orderDetail.unitCode,
|
unitCode: item.unitCode || orderDetail.unitCode,
|
||||||
categoryCode: item.categoryCode ?? orderDetail.categoryCode,
|
|
||||||
unitCodeName: item.unitCodeName || orderDetail.unitCode_dictText,
|
unitCodeName: item.unitCodeName || orderDetail.unitCode_dictText,
|
||||||
minUnitCode: orderDetail.minUnitCode,
|
minUnitCode: orderDetail.minUnitCode,
|
||||||
doseUnitCode: orderDetail.doseUnitCode,
|
doseUnitCode: orderDetail.doseUnitCode,
|
||||||
|
|
||||||
// 合并后的完整对象(用于 setValue)
|
// 合并后的完整对象(用于 setValue)
|
||||||
// 先展开 orderDetail 获取所有药品基础字段(categoryCode、minUnitCode、doseUnitCode、
|
|
||||||
// partPercent、partAttributeEnum、unitConversionRatio、defaultLotNumber 等),
|
|
||||||
// 再用组套用户覆盖值覆盖,确保单次剂量/频次/用法/用药天数/总量等不被丢失
|
|
||||||
mergedDetail: {
|
mergedDetail: {
|
||||||
...orderDetail,
|
...orderDetail,
|
||||||
adviceName: orderDetail.adviceName || item.orderDefinitionName || '未知项目',
|
adviceName: orderDetail.adviceName || item.orderDefinitionName || '未知项目',
|
||||||
adviceType: orderDetail.adviceType,
|
adviceType: orderDetail.adviceType,
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
unitCode: item.unitCode ?? orderDetail.unitCode,
|
unitCode: item.unitCode || orderDetail.unitCode,
|
||||||
categoryCode: item.categoryCode ?? orderDetail.categoryCode,
|
|
||||||
unitCodeName: item.unitCodeName,
|
unitCodeName: item.unitCodeName,
|
||||||
dose: item.dose ?? orderDetail.dose,
|
dose: item.dose || orderDetail.dose,
|
||||||
rateCode: item.rateCode ?? orderDetail.rateCode,
|
rateCode: item.rateCode || orderDetail.rateCode,
|
||||||
methodCode: item.methodCode ?? orderDetail.methodCode,
|
methodCode: item.methodCode || orderDetail.methodCode,
|
||||||
dispensePerDuration: item.dispensePerDuration ?? orderDetail.dispensePerDuration,
|
dispensePerDuration: item.dispensePerDuration || orderDetail.dispensePerDuration,
|
||||||
doseQuantity: item.doseQuantity ?? orderDetail.doseQuantity,
|
doseQuantity: item.doseQuantity,
|
||||||
// 🔧 Bug #218 / #403 修复:positionId 可能存储在 item 本身,优先使用 item.positionId
|
inventoryList: orderDetail.inventoryList || [],
|
||||||
positionId: item.positionId ?? orderDetail.positionId,
|
priceList: orderDetail.priceList || [],
|
||||||
// 执行科室:优先使用组套明细中保存的 orgId
|
partPercent: orderDetail.partPercent || 1,
|
||||||
orgId: item.orgId ?? orderDetail.orgId,
|
// 🔧 Bug #218 修复:positionId 可能存储在 item 本身,优先使用 item.positionId
|
||||||
orgName: item.orgName ?? orderDetail.orgName,
|
positionId: item.positionId || orderDetail.positionId,
|
||||||
// 组号(保留组套中的分组信息)
|
defaultLotNumber: orderDetail.defaultLotNumber,
|
||||||
groupId: item.groupId,
|
|
||||||
groupOrder: item.groupOrder,
|
|
||||||
therapyEnum: item.therapyEnum ?? orderDetail.therapyEnum ?? '1',
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3326,13 +3326,9 @@ function syncGroupFields(row) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 同步执行科室
|
// 同步执行科室
|
||||||
// 🔧 Bug #455: 诊疗类医嘱(adviceType=3)不使用项目配置的执行科室,
|
|
||||||
// 避免配置ID不在机构树中导致显示原始ID,保持患者就诊科室即可
|
|
||||||
if (row.orgId || row.positionId) {
|
if (row.orgId || row.positionId) {
|
||||||
if (Number(row.adviceType) != 3) {
|
// 🔧 修复:优先使用项目所属科室(orgId),其次positionId
|
||||||
// 🔧 修复:优先使用项目所属科室(orgId),其次positionId
|
prescriptionList.value[rowIndex.value].orgId = row.orgId || row.positionId;
|
||||||
prescriptionList.value[rowIndex.value].orgId = row.orgId || row.positionId;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同步皮试标记
|
// 同步皮试标记
|
||||||
@@ -3416,11 +3412,8 @@ async function setValue(row) {
|
|||||||
showPopover: false, // 确保查询框关闭
|
showPopover: false, // 确保查询框关闭
|
||||||
};
|
};
|
||||||
console.log('[BugFix] setValue - prescriptionList[rowIndex].adviceType_dictText:', prescriptionList.value[rowIndex.value].adviceType_dictText);
|
console.log('[BugFix] setValue - prescriptionList[rowIndex].adviceType_dictText:', prescriptionList.value[rowIndex.value].adviceType_dictText);
|
||||||
// 🔧 Bug #455: 诊疗医嘱(adviceType=3)的执行科室默认使用患者就诊科室,
|
// 🔧 Bug #455: 执行科室默认逻辑:使用positionId(诊疗执行科室配置) → 患者就诊科室,不再使用row.orgId(项目所属科室)
|
||||||
// 不使用positionId(诊疗目录配置的执行科室),避免配置ID不在机构树中导致显示原始ID
|
prescriptionList.value[rowIndex.value].orgId = row.positionId || props.patientInfo?.orgId;
|
||||||
if (Number(row.adviceType) != 3) {
|
|
||||||
prescriptionList.value[rowIndex.value].orgId = row.positionId || props.patientInfo?.orgId;
|
|
||||||
}
|
|
||||||
prescriptionList.value[rowIndex.value].dose = row.dose || row.doseQuantity;
|
prescriptionList.value[rowIndex.value].dose = row.dose || row.doseQuantity;
|
||||||
prescriptionList.value[rowIndex.value].quantity = row.quantity || 1;
|
prescriptionList.value[rowIndex.value].quantity = row.quantity || 1;
|
||||||
prescriptionList.value[rowIndex.value].unitCodeList = unitCodeList.value;
|
prescriptionList.value[rowIndex.value].unitCodeList = unitCodeList.value;
|
||||||
|
|||||||
@@ -1133,17 +1133,13 @@ function submitForm() {
|
|||||||
// 新增手术
|
// 新增手术
|
||||||
addSurgery(form.value).then((res) => {
|
addSurgery(form.value).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
proxy.$modal.msgSuccess('手术申请提交成功!')
|
proxy.$modal.msgSuccess(res.msg || '手术申请提交成功!')
|
||||||
// 保存麻醉方式
|
// 保存麻醉方式
|
||||||
sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum)
|
sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum)
|
||||||
open.value = false
|
open.value = false
|
||||||
emit('saved') // 通知父组件刷新医嘱列表
|
emit('saved') // 通知父组件刷新医嘱列表
|
||||||
// 刷新手术申请列表,使用 nextTick 确保数据一致性
|
// 刷新手术申请列表
|
||||||
proxy.$nextTick(() => {
|
getList()
|
||||||
if (props.patientInfo?.encounterId) {
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
proxy.$modal.msgError(res.msg || '新增手术失败,请检查表单信息')
|
proxy.$modal.msgError(res.msg || '新增手术失败,请检查表单信息')
|
||||||
}
|
}
|
||||||
@@ -1155,17 +1151,13 @@ function submitForm() {
|
|||||||
// 修改手术
|
// 修改手术
|
||||||
updateSurgery(form.value).then((res) => {
|
updateSurgery(form.value).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
proxy.$modal.msgSuccess('手术申请修改成功!')
|
proxy.$modal.msgSuccess(res.msg || '手术申请修改成功!')
|
||||||
// 保存麻醉方式
|
// 保存麻醉方式
|
||||||
sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum)
|
sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum)
|
||||||
open.value = false
|
open.value = false
|
||||||
emit('saved') // 通知父组件刷新医嘱列表
|
emit('saved') // 通知父组件刷新医嘱列表
|
||||||
// 刷新手术申请列表,使用 nextTick 确保数据一致性
|
// 刷新手术申请列表
|
||||||
proxy.$nextTick(() => {
|
getList()
|
||||||
if (props.patientInfo?.encounterId) {
|
|
||||||
getList()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
proxy.$modal.msgError(res.msg || '更新手术失败,请检查表单信息')
|
proxy.$modal.msgError(res.msg || '更新手术失败,请检查表单信息')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,17 +44,6 @@ export function getSurgery(queryParams) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 分页查询手术申请单(全局,不需要encounterId,用于门诊手术安排查找弹窗)
|
|
||||||
*/
|
|
||||||
export function getSurgeryPage(queryParams) {
|
|
||||||
return request({
|
|
||||||
url: '/reg-doctorstation/request-form/get-surgery-page',
|
|
||||||
method: 'get',
|
|
||||||
params: queryParams,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询护理医嘱信息
|
* 查询护理医嘱信息
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||||
<el-table-column prop="name" label="申请单名称" width="140" />
|
<el-table-column prop="name" label="申请单名称" width="140" />
|
||||||
<el-table-column prop="createTime" label="创建时间" width="160" />
|
<el-table-column prop="createTime" label="创建时间" width="160" />
|
||||||
<el-table-column prop="prescriptionNo" label="申请单号" width="140" />
|
<el-table-column prop="prescriptionNo" label="处方号" width="140" />
|
||||||
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
|
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
|
||||||
<el-table-column label="申请单状态" width="120" align="center">
|
<el-table-column label="申请单状态" width="120" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
<el-descriptions-item label="创建时间">{{
|
<el-descriptions-item label="创建时间">{{
|
||||||
currentDetail.createTime || '-'
|
currentDetail.createTime || '-'
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="申请单号">{{
|
<el-descriptions-item label="处方号">{{
|
||||||
currentDetail.prescriptionNo || '-'
|
currentDetail.prescriptionNo || '-'
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="申请者">{{
|
<el-descriptions-item label="申请者">{{
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
<el-descriptions title="申请单描述" :column="2">
|
<el-descriptions title="申请单描述" :column="2">
|
||||||
<template v-for="(value, key) in descJsonData" :key="key">
|
<template v-for="(value, key) in descJsonData" :key="key">
|
||||||
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
|
<el-descriptions-item v-if="isFieldMatched(key)" :label="getFieldLabel(key)">
|
||||||
{{ transformField(key, value) || '-' }}
|
{{ value || '-' }}
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
</template>
|
</template>
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
@@ -270,12 +270,6 @@ const parseStatus = (status) => {
|
|||||||
const labelMap = {
|
const labelMap = {
|
||||||
categoryType: '项目类别',
|
categoryType: '项目类别',
|
||||||
targetDepartment: '发往科室',
|
targetDepartment: '发往科室',
|
||||||
urgencyLevel: '紧急程度',
|
|
||||||
allergyHistory: '过敏史',
|
|
||||||
examinationPurpose: '检查目的',
|
|
||||||
expectedExaminationTime: '期望检查时间',
|
|
||||||
medicalHistorySummary: '病史摘要',
|
|
||||||
allergyConfirmed: '过敏确认',
|
|
||||||
symptom: '症状',
|
symptom: '症状',
|
||||||
sign: '体征',
|
sign: '体征',
|
||||||
clinicalDiagnosis: '临床诊断',
|
clinicalDiagnosis: '临床诊断',
|
||||||
@@ -284,17 +278,6 @@ const labelMap = {
|
|||||||
attention: '注意事项',
|
attention: '注意事项',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Fields that need value transformation before display
|
|
||||||
const transformField = (key, value) => {
|
|
||||||
if (key === 'urgencyLevel') {
|
|
||||||
return value === 'emergency' ? '急诊' : '普通';
|
|
||||||
}
|
|
||||||
if (key === 'allergyConfirmed') {
|
|
||||||
return value === true || value === 'true' ? '已口头确认' : '未确认';
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isFieldMatched = (key) => {
|
const isFieldMatched = (key) => {
|
||||||
return key in labelMap;
|
return key in labelMap;
|
||||||
};
|
};
|
||||||
@@ -309,45 +292,50 @@ const hasMatchedFields = computed(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/** 查询科室 */
|
/** 查询科室 */
|
||||||
const getLocationInfo = async () => {
|
const getLocationInfo = () => {
|
||||||
try {
|
getDepartmentList().then((res) => {
|
||||||
const res = await getDepartmentList();
|
orgOptions.value = res.data || [];
|
||||||
orgOptions.value = Array.isArray(res.data) ? res.data : [];
|
});
|
||||||
} catch (e) {
|
|
||||||
console.warn('科室列表加载失败:', e.message);
|
|
||||||
orgOptions.value = [];
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 递归查找树形科室节点
|
const recursionFun = (targetDepartment) => {
|
||||||
const findTreeItem = (list, id) => {
|
let name = '';
|
||||||
if (!list || list.length === 0) return null;
|
for (let index = 0; index < orgOptions.value.length; index++) {
|
||||||
for (const item of list) {
|
const obj = orgOptions.value[index];
|
||||||
if (item.id == id) return item;
|
if (obj.id == targetDepartment) {
|
||||||
if (item.children && item.children.length > 0) {
|
name = obj.name;
|
||||||
const found = findTreeItem(item.children, id);
|
}
|
||||||
if (found) return found;
|
const subObjArray = obj['children'];
|
||||||
|
if (subObjArray && subObjArray.length > 0) {
|
||||||
|
for (let index = 0; index < subObjArray.length; index++) {
|
||||||
|
const item = subObjArray[index];
|
||||||
|
if (item.id == targetDepartment) {
|
||||||
|
name = item.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return name;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleViewDetail = async (row) => {
|
const handleViewDetail = async (row) => {
|
||||||
// 确保科室数据已加载,以便将 ID 解析为名称
|
console.log('targetDepartment========>', JSON.stringify(row));
|
||||||
if (!orgOptions.value || orgOptions.value.length === 0) {
|
|
||||||
await getLocationInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDetail.value = row;
|
currentDetail.value = row;
|
||||||
// 解析 descJson
|
// 解析 descJson
|
||||||
if (row.descJson) {
|
if (row.descJson) {
|
||||||
try {
|
try {
|
||||||
const obj = JSON.parse(row.descJson);
|
const obj = JSON.parse(row.descJson);
|
||||||
// 将发往科室 ID 转换为名称
|
// 确保科室数据已加载
|
||||||
if (obj.targetDepartment) {
|
if (!orgOptions.value || orgOptions.value.length === 0) {
|
||||||
const deptItem = findTreeItem(orgOptions.value, obj.targetDepartment);
|
await new Promise((resolve) => {
|
||||||
obj.targetDepartment = deptItem ? deptItem.name : obj.targetDepartment;
|
getDepartmentList().then((res) => {
|
||||||
|
orgOptions.value = res.data || [];
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
obj.targetDepartment = recursionFun(obj.targetDepartment);
|
||||||
descJsonData.value = obj;
|
descJsonData.value = obj;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('解析 descJson 失败:', e);
|
console.error('解析 descJson 失败:', e);
|
||||||
|
|||||||
@@ -82,11 +82,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<el-table-column type="index" label="序号" width="60" align="center" />
|
<el-table-column type="index" label="序号" width="60" align="center" />
|
||||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||||
<el-table-column label="申请单名称" width="140">
|
<el-table-column prop="name" label="申请单名称" width="140" />
|
||||||
<template #default="scope">
|
|
||||||
<span>{{ buildApplicationName(scope.row) }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="createTime" label="创建时间" width="160" />
|
<el-table-column prop="createTime" label="创建时间" width="160" />
|
||||||
<el-table-column prop="prescriptionNo" label="申请单号" width="140" />
|
<el-table-column prop="prescriptionNo" label="申请单号" width="140" />
|
||||||
<el-table-column label="单据状态" width="100" align="center">
|
<el-table-column label="单据状态" width="100" align="center">
|
||||||
@@ -107,11 +103,11 @@
|
|||||||
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
|
<el-table-column prop="requesterId_dictText" label="申请者" width="120" />
|
||||||
<el-table-column label="操作" align="center" fixed="right" width="160">
|
<el-table-column label="操作" align="center" fixed="right" width="160">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<template v-if="scope.row.status == 0">
|
<template v-if="scope.row.billStatus == 0 || scope.row.status == 0">
|
||||||
<el-button link type="primary" @click="handleEdit(scope.row)">修改</el-button>
|
<el-button link type="primary" @click="handleEdit(scope.row)">修改</el-button>
|
||||||
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
<el-button link type="danger" @click="handleDelete(scope.row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="scope.row.status == 1">
|
<template v-else-if="scope.row.billStatus == 1 || scope.row.status == 1">
|
||||||
<el-button link type="warning" @click="handleWithdraw(scope.row)">撤回</el-button>
|
<el-button link type="warning" @click="handleWithdraw(scope.row)">撤回</el-button>
|
||||||
</template>
|
</template>
|
||||||
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
|
<el-button link type="primary" @click="handleViewDetail(scope.row)">详情</el-button>
|
||||||
@@ -141,7 +137,7 @@
|
|||||||
<el-descriptions-item label="创建时间">{{
|
<el-descriptions-item label="创建时间">{{
|
||||||
currentDetail.createTime || '-'
|
currentDetail.createTime || '-'
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="申请单号">{{
|
<el-descriptions-item label="处方号">{{
|
||||||
currentDetail.prescriptionNo || '-'
|
currentDetail.prescriptionNo || '-'
|
||||||
}}</el-descriptions-item>
|
}}</el-descriptions-item>
|
||||||
<el-descriptions-item label="申请者">{{
|
<el-descriptions-item label="申请者">{{
|
||||||
@@ -191,7 +187,7 @@ import {computed, getCurrentInstance, ref, watch} from 'vue';
|
|||||||
import {Refresh, Search} from '@element-plus/icons-vue';
|
import {Refresh, Search} from '@element-plus/icons-vue';
|
||||||
import {patientInfo} from '../../store/patient.js';
|
import {patientInfo} from '../../store/patient.js';
|
||||||
import {getInspection, deleteRequestForm, withdrawRequestForm} from './api';
|
import {getInspection, deleteRequestForm, withdrawRequestForm} from './api';
|
||||||
import {getDepartmentList} from '@/api/public.js';
|
import {getOrgList} from '@/views/doctorstation/components/api.js';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
|
|
||||||
@@ -289,9 +285,6 @@ const labelMap = {
|
|||||||
otherDiagnosis: '其他诊断',
|
otherDiagnosis: '其他诊断',
|
||||||
relatedResult: '相关结果',
|
relatedResult: '相关结果',
|
||||||
attention: '注意事项',
|
attention: '注意事项',
|
||||||
applicationType: '申请类型',
|
|
||||||
specimenName: '标本类型',
|
|
||||||
executeTime: '执行时间',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -318,8 +311,8 @@ const parsePriorityCode = (descJson) => {
|
|||||||
if (!descJson) return '-';
|
if (!descJson) return '-';
|
||||||
try {
|
try {
|
||||||
const obj = JSON.parse(descJson);
|
const obj = JSON.parse(descJson);
|
||||||
// applicationType: 0-普通, 1-急诊
|
// priorityCode: 0-普通, 1-急
|
||||||
return obj.applicationType === 1 ? '急' : '普通';
|
return obj.priorityCode === 1 ? '急' : '普通';
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('解析 descJson 失败:', e);
|
console.error('解析 descJson 失败:', e);
|
||||||
return '-';
|
return '-';
|
||||||
@@ -343,24 +336,6 @@ const parseSpecimenType = (descJson) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据申请单详情构建申请单名称
|
|
||||||
* 单一项目:显示项目名称+数量
|
|
||||||
* 多个项目:显示首个项目名称+数量+"等X项"
|
|
||||||
*/
|
|
||||||
const buildApplicationName = (row) => {
|
|
||||||
const details = row.requestFormDetailList;
|
|
||||||
if (!details || details.length === 0) {
|
|
||||||
return row.name || '-';
|
|
||||||
}
|
|
||||||
if (details.length === 1) {
|
|
||||||
const item = details[0];
|
|
||||||
return `${item.adviceName}${item.quantity || ''}`;
|
|
||||||
}
|
|
||||||
const first = details[0];
|
|
||||||
return `${first.adviceName}${first.quantity || ''}等${details.length}项`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const isFieldMatched = (key) => {
|
const isFieldMatched = (key) => {
|
||||||
return key in labelMap;
|
return key in labelMap;
|
||||||
};
|
};
|
||||||
@@ -416,9 +391,6 @@ const handleViewDetail = async (row) => {
|
|||||||
try {
|
try {
|
||||||
const obj = JSON.parse(row.descJson);
|
const obj = JSON.parse(row.descJson);
|
||||||
obj.targetDepartment = recursionFun(obj.targetDepartment);
|
obj.targetDepartment = recursionFun(obj.targetDepartment);
|
||||||
// 转换申请类型编码为可读文本
|
|
||||||
if (obj.applicationType === 0) obj.applicationType = '普通';
|
|
||||||
else if (obj.applicationType === 1) obj.applicationType = '急诊';
|
|
||||||
descJsonData.value = obj;
|
descJsonData.value = obj;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('解析 descJson 失败:', e);
|
console.error('解析 descJson 失败:', e);
|
||||||
|
|||||||
@@ -72,45 +72,6 @@
|
|||||||
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
|
<el-input v-model="form.attention" autocomplete="off" type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- 申请类型 -->
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="申请类型" prop="applicationType" style="width: 100%">
|
|
||||||
<el-radio-group v-model="form.applicationType">
|
|
||||||
<el-radio :value="0">普通</el-radio>
|
|
||||||
<el-radio :value="1">急诊</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<!-- 标本类型 -->
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="标本类型" prop="specimenName" style="width: 100%">
|
|
||||||
<el-select v-model="form.specimenName" placeholder="请选择标本类型" style="width: 100%">
|
|
||||||
<el-option label="血液" value="血液" />
|
|
||||||
<el-option label="尿液" value="尿液" />
|
|
||||||
<el-option label="粪便" value="粪便" />
|
|
||||||
<el-option label="痰液" value="痰液" />
|
|
||||||
<el-option label="咽拭子" value="咽拭子" />
|
|
||||||
<el-option label="脑脊液" value="脑脊液" />
|
|
||||||
<el-option label="胸腹水" value="胸腹水" />
|
|
||||||
<el-option label="关节液" value="关节液" />
|
|
||||||
<el-option label="分泌物" value="分泌物" />
|
|
||||||
<el-option label="其他" value="其他" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<!-- 执行时间 -->
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="执行时间" prop="executeTime" style="width: 100%">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="form.executeTime"
|
|
||||||
type="datetime"
|
|
||||||
placeholder="选择执行时间"
|
|
||||||
format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
value-format="YYYY-MM-DD HH:mm:ss"
|
|
||||||
style="width: 100%"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
@@ -144,56 +105,42 @@ const applicationListAll = ref();
|
|||||||
const applicationList = ref();
|
const applicationList = ref();
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const orgOptions = ref([]); // 科室选项
|
const orgOptions = ref([]); // 科室选项
|
||||||
const getList = async () => {
|
const getList = () => {
|
||||||
if (!patientInfo.value?.inHospitalOrgId) {
|
if (!patientInfo.value?.inHospitalOrgId) {
|
||||||
applicationList.value = [];
|
applicationList.value = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
getApplicationList({
|
||||||
const allRecords = [];
|
pageSize: 9999,
|
||||||
let currentPage = 1;
|
pageNum: 1,
|
||||||
const pageSize = 500;
|
categoryCode: '22',
|
||||||
|
organizationId: patientInfo.value.inHospitalOrgId,
|
||||||
// 分页拉取全部数据(后端单页最多500条)
|
adviceTypes: [3], //1 药品 2耗材 3诊疗
|
||||||
while (true) {
|
})
|
||||||
const res = await getApplicationList({
|
.then((res) => {
|
||||||
pageSize,
|
if (res.code === 200) {
|
||||||
pageNo: currentPage,
|
applicationListAll.value = res.data.records;
|
||||||
categoryCode: '22',
|
applicationList.value = res.data.records.map((item) => {
|
||||||
organizationId: patientInfo.value.inHospitalOrgId,
|
const priceInfo = item.priceList?.[0] || {};
|
||||||
adviceTypes: [3], // 1 药品 2 耗材 3 诊疗
|
const price = priceInfo.price != null ? Number(priceInfo.price).toFixed(2) : '0.00';
|
||||||
});
|
const unit = item.unitCode_dictText || item.unitCode || '';
|
||||||
if (res.code !== 200) {
|
return {
|
||||||
|
adviceDefinitionId: item.adviceDefinitionId,
|
||||||
|
orgId: item.orgId,
|
||||||
|
label: item.adviceName + ' (¥' + price + '/' + unit + ')',
|
||||||
|
key: item.adviceDefinitionId,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
console.log('applicationList========>', JSON.stringify(res.data.records));
|
||||||
|
} else {
|
||||||
proxy.$message.error(res.message);
|
proxy.$message.error(res.message);
|
||||||
applicationList.value = [];
|
applicationList.value = [];
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const records = res.data?.records || [];
|
})
|
||||||
allRecords.push(...records);
|
.finally(() => {
|
||||||
// 当前页不足 pageSize 或已无数据,说明已全部拉取
|
loading.value = false;
|
||||||
if (records.length < pageSize) break;
|
|
||||||
currentPage++;
|
|
||||||
}
|
|
||||||
|
|
||||||
applicationListAll.value = allRecords;
|
|
||||||
applicationList.value = allRecords.map((item) => {
|
|
||||||
const priceInfo = item.priceList?.[0] || {};
|
|
||||||
const price = priceInfo.price != null ? Number(priceInfo.price).toFixed(2) : '0.00';
|
|
||||||
const unit = item.unitCode_dictText || item.unitCode || '';
|
|
||||||
return {
|
|
||||||
adviceDefinitionId: item.adviceDefinitionId,
|
|
||||||
orgId: item.orgId,
|
|
||||||
label: item.adviceName + ' (¥' + price + '/' + unit + ')',
|
|
||||||
key: item.adviceDefinitionId,
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
} catch (e) {
|
|
||||||
proxy.$message.error('获取检验项目列表失败');
|
|
||||||
applicationList.value = [];
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const transferValue = ref([]);
|
const transferValue = ref([]);
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
@@ -205,9 +152,6 @@ const form = reactive({
|
|||||||
otherDiagnosis: '', // 其他诊断
|
otherDiagnosis: '', // 其他诊断
|
||||||
relatedResult: '', // 相关结果
|
relatedResult: '', // 相关结果
|
||||||
attention: '', // 注意事项
|
attention: '', // 注意事项
|
||||||
applicationType: 0, // 申请类型 0-普通 1-急诊
|
|
||||||
specimenName: '血液', // 标本类型
|
|
||||||
executeTime: null, // 执行时间
|
|
||||||
primaryDiagnosisList: [], //主诊断目录
|
primaryDiagnosisList: [], //主诊断目录
|
||||||
otherDiagnosisList: [], //其他断目录
|
otherDiagnosisList: [], //其他断目录
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -483,10 +483,7 @@ const submit = () => {
|
|||||||
encounterId: patientInfo.value.encounterId,
|
encounterId: patientInfo.value.encounterId,
|
||||||
organizationId: patientInfo.value.inHospitalOrgId,
|
organizationId: patientInfo.value.inHospitalOrgId,
|
||||||
requestFormId: '',
|
requestFormId: '',
|
||||||
name: transferValue.value.map(id => {
|
name: applicationListAllFilter.map(item => item.adviceName).join('、'),
|
||||||
const item = applicationListAll.value?.find(i => i.adviceDefinitionId === id);
|
|
||||||
return item?.adviceName || '';
|
|
||||||
}).filter(Boolean).join('、'),
|
|
||||||
descJson: JSON.stringify(submitForm),
|
descJson: JSON.stringify(submitForm),
|
||||||
categoryEnum: '2',
|
categoryEnum: '2',
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
|
|||||||
@@ -5,14 +5,16 @@
|
|||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<div class="surgery-container">
|
<div class="surgery-container">
|
||||||
<div v-loading="loading" class="transfer-wrapper" style="min-height: 300px;">
|
<div class="transfer-wrapper">
|
||||||
<el-transfer
|
<div v-loading="loading" style="min-height: 300px;">
|
||||||
v-model="transferValue"
|
<el-transfer
|
||||||
:data="applicationList"
|
v-model="transferValue"
|
||||||
filter-placeholder="项目代码/名称"
|
:data="applicationList"
|
||||||
filterable
|
filter-placeholder="项目代码/名称"
|
||||||
:titles="['未选择', '已选择']"
|
filterable
|
||||||
/>
|
:titles="['未选择', '已选择']"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bloodTransfusion-form">
|
<div class="bloodTransfusion-form">
|
||||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
|
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
|
||||||
@@ -86,9 +88,6 @@ import {getApplicationList, saveSurgery} from './api';
|
|||||||
import {ElMessage} from 'element-plus';
|
import {ElMessage} from 'element-plus';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance();
|
const { proxy } = getCurrentInstance();
|
||||||
// 模块级缓存:避免每次打开弹窗都重新请求手术项目列表
|
|
||||||
let surgeryRecordsCache = null; // 原始 API 记录
|
|
||||||
let surgeryMappedCache = null; // 映射后的 el-transfer 数据
|
|
||||||
// 递归查找树形科室节点
|
// 递归查找树形科室节点
|
||||||
const findTreeItem = (list, id) => {
|
const findTreeItem = (list, id) => {
|
||||||
if (!list || list.length === 0) return null;
|
if (!list || list.length === 0) return null;
|
||||||
@@ -104,8 +103,8 @@ const findTreeItem = (list, id) => {
|
|||||||
const emits = defineEmits(['submitOk']);
|
const emits = defineEmits(['submitOk']);
|
||||||
const props = defineProps({});
|
const props = defineProps({});
|
||||||
const state = reactive({});
|
const state = reactive({});
|
||||||
const applicationListAll = ref();
|
const applicationListAll = ref([]);
|
||||||
const applicationList = ref();
|
const applicationList = ref([]);
|
||||||
const orgOptions = ref([]); // 科室选项
|
const orgOptions = ref([]); // 科室选项
|
||||||
const loading = ref(false); // 加载状态
|
const loading = ref(false); // 加载状态
|
||||||
const getList = () => {
|
const getList = () => {
|
||||||
@@ -113,12 +112,6 @@ const getList = () => {
|
|||||||
applicationList.value = [];
|
applicationList.value = [];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 命中缓存时直接使用,避免重复请求导致加载缓慢
|
|
||||||
if (surgeryMappedCache && surgeryMappedCache.length > 0) {
|
|
||||||
applicationList.value = surgeryMappedCache;
|
|
||||||
applicationListAll.value = surgeryRecordsCache;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
getApplicationList({
|
getApplicationList({
|
||||||
pageSize: 500,
|
pageSize: 500,
|
||||||
@@ -141,9 +134,6 @@ const getList = () => {
|
|||||||
key: item.adviceDefinitionId,
|
key: item.adviceDefinitionId,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
// 写入模块缓存,后续打开弹窗直接复用
|
|
||||||
surgeryRecordsCache = res.data.records;
|
|
||||||
surgeryMappedCache = applicationList.value;
|
|
||||||
} else {
|
} else {
|
||||||
console.warn('获取手术项目列表失败:', res.message);
|
console.warn('获取手术项目列表失败:', res.message);
|
||||||
applicationList.value = [];
|
applicationList.value = [];
|
||||||
|
|||||||
@@ -197,7 +197,6 @@
|
|||||||
style="width: 62%"
|
style="width: 62%"
|
||||||
v-model="scope.row.adviceName"
|
v-model="scope.row.adviceName"
|
||||||
placeholder="请选择项目"
|
placeholder="请选择项目"
|
||||||
@input="handleChange"
|
|
||||||
@click="handleFocus(scope.row, scope.$index)"
|
@click="handleFocus(scope.row, scope.$index)"
|
||||||
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
|
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
|
||||||
@keydown="
|
@keydown="
|
||||||
@@ -710,17 +709,9 @@ function loadConfiguredCategories() {
|
|||||||
// 数据过滤
|
// 数据过滤
|
||||||
const filterPrescriptionList = computed(() => {
|
const filterPrescriptionList = computed(() => {
|
||||||
const pList = prescriptionList.value.filter((item) => {
|
const pList = prescriptionList.value.filter((item) => {
|
||||||
// 修复 Bug #488:orderClassCode 可能是复合值 '1-2',需提取 adviceType 部分进行比较
|
|
||||||
let matchAdviceType = true;
|
|
||||||
if (orderClassCode.value) {
|
|
||||||
const filterAdviceType = String(orderClassCode.value).includes('-')
|
|
||||||
? parseInt(String(orderClassCode.value).split('-')[0])
|
|
||||||
: orderClassCode.value;
|
|
||||||
matchAdviceType = filterAdviceType == item.adviceType;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
(!therapyEnum.value || therapyEnum.value == item.therapyEnum) &&
|
(!therapyEnum.value || therapyEnum.value == item.therapyEnum) &&
|
||||||
matchAdviceType &&
|
(!orderClassCode.value || orderClassCode.value == item.adviceType) &&
|
||||||
(!orderStatus.value || (orderStatus.value == item.statusEnum && item.requestId))
|
(!orderStatus.value || (orderStatus.value == item.statusEnum && item.requestId))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -748,28 +739,12 @@ function getRowDisabled(row) {
|
|||||||
/**
|
/**
|
||||||
* 将行的 adviceType + categoryCode 映射为 el-select 的选中值
|
* 将行的 adviceType + categoryCode 映射为 el-select 的选中值
|
||||||
* 药品子分类使用复合值如 '1-2'(adviceType-categoryCode),诊疗/手术/全部使用原始值
|
* 药品子分类使用复合值如 '1-2'(adviceType-categoryCode),诊疗/手术/全部使用原始值
|
||||||
* 修复 Bug #488:当行的 adviceType 在当前配置中找不到匹配选项时,返回最接近的可用值,避免回显为纯数字
|
|
||||||
*/
|
*/
|
||||||
function getRowSelectValue(row) {
|
function getRowSelectValue(row) {
|
||||||
if (row.adviceType == 1 && row.categoryCode) {
|
if (row.adviceType == 1 && row.categoryCode) {
|
||||||
const compositeValue = '1-' + row.categoryCode;
|
return '1-' + row.categoryCode;
|
||||||
// 检查复合值是否在选项列表中
|
|
||||||
if (adviceTypeList.value.some(item => item.value === compositeValue)) {
|
|
||||||
return compositeValue;
|
|
||||||
}
|
|
||||||
// 配置的 categoryCode 已变更,回退到第一个药品选项
|
|
||||||
const firstPharmacy = adviceTypeList.value.find(item => String(item.value).startsWith('1-'));
|
|
||||||
if (firstPharmacy) {
|
|
||||||
return firstPharmacy.value;
|
|
||||||
}
|
|
||||||
return row.adviceType;
|
|
||||||
}
|
}
|
||||||
// 诊疗/手术等非药品类型,检查其值是否在选项列表中
|
return row.adviceType;
|
||||||
if (adviceTypeList.value.some(item => item.value === row.adviceType)) {
|
|
||||||
return row.adviceType;
|
|
||||||
}
|
|
||||||
// 不在选项中的值(如已废弃的 adviceType),返回 undefined 让 el-select 显示为空
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增医嘱
|
// 新增医嘱
|
||||||
@@ -1206,27 +1181,19 @@ function handleSave() {
|
|||||||
});
|
});
|
||||||
// 此处签发处方和单行保存处方传参相同,后台已经将传参存为JSON字符串,此处直接转换为JSON即可
|
// 此处签发处方和单行保存处方传参相同,后台已经将传参存为JSON字符串,此处直接转换为JSON即可
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
let list = [];
|
let list = saveList.map((item) => {
|
||||||
try {
|
const parsedContent = JSON.parse(item.contentJson);
|
||||||
list = saveList.map((item) => {
|
return {
|
||||||
const parsedContent = item.contentJson ? JSON.parse(item.contentJson) || {} : {};
|
...parsedContent,
|
||||||
return {
|
adviceType: item.adviceType,
|
||||||
...parsedContent,
|
requestId: item.requestId,
|
||||||
adviceType: item.adviceType,
|
dbOpType: '1',
|
||||||
requestId: item.requestId,
|
groupId: item.groupId,
|
||||||
dbOpType: '1',
|
uniqueKey: undefined,
|
||||||
groupId: item.groupId,
|
// 确保 therapyEnum 被正确传递
|
||||||
uniqueKey: undefined,
|
therapyEnum: parsedContent.therapyEnum || item.therapyEnum || '1',
|
||||||
// 确保 therapyEnum 被正确传递
|
};
|
||||||
therapyEnum: parsedContent.therapyEnum || item.therapyEnum || '1',
|
});
|
||||||
};
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
loading.value = false;
|
|
||||||
isSaving.value = false;
|
|
||||||
proxy.$modal.msgError('医嘱内容解析失败,请检查待签发医嘱');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 保存签发按钮
|
// 保存签发按钮
|
||||||
isSaving.value = true;
|
isSaving.value = true;
|
||||||
console.log('签发处方参数:', {
|
console.log('签发处方参数:', {
|
||||||
@@ -1243,7 +1210,7 @@ function handleSave() {
|
|||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
getListInfo(false);
|
getListInfo(false);
|
||||||
bindMethod.value = {};
|
bindMethod.value = {};
|
||||||
nextId.value = 1;
|
nextId.value == 1;
|
||||||
} else {
|
} else {
|
||||||
proxy.$modal.msgError(res.message);
|
proxy.$modal.msgError(res.message);
|
||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
@@ -1344,12 +1311,11 @@ function handleCancelEdit(row, index) {
|
|||||||
|
|
||||||
function handleSaveSign(row, index) {
|
function handleSaveSign(row, index) {
|
||||||
if (row.adviceType != 2) {
|
if (row.adviceType != 2) {
|
||||||
// 修复 Bug #488:严格校验 itemNo,确保非空且为有效字符串才发起请求
|
|
||||||
let itemNo = row.adviceType == 1 ? row.methodCode : row.adviceDefinitionId;
|
let itemNo = row.adviceType == 1 ? row.methodCode : row.adviceDefinitionId;
|
||||||
if (!itemNo || String(itemNo).trim() === '') {
|
if (!itemNo) {
|
||||||
console.warn('绑定设备检查跳过:itemNo为空(adviceType=' + row.adviceType + ', adviceName=' + row.adviceName + ')');
|
console.warn('绑定设备检查跳过:itemNo为空(adviceType=' + row.adviceType + ', adviceName=' + row.adviceName + ')');
|
||||||
} else {
|
} else {
|
||||||
getBindDevice({ typeCode: row.adviceType, itemNo: String(itemNo) }).then((res) => {
|
getBindDevice({ typeCode: row.adviceType, itemNo: itemNo }).then((res) => {
|
||||||
if (res.data.length == 0) {
|
if (res.data.length == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1410,21 +1376,13 @@ function handleSaveSign(row, index) {
|
|||||||
savePrescription({ regAdviceSaveList: [row] }).then((res) => {
|
savePrescription({ regAdviceSaveList: [row] }).then((res) => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
proxy.$modal.msgSuccess('保存成功');
|
proxy.$modal.msgSuccess('保存成功');
|
||||||
nextId.value = 1;
|
nextId.value == 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 新增行:调用保存接口将数据持久化到后端
|
if (prescriptionList.value[0].adviceName) {
|
||||||
row.dbOpType = '1';
|
handleAddPrescription();
|
||||||
savePrescription({ regAdviceSaveList: [row] }).then((res) => {
|
}
|
||||||
if (res.code === 200) {
|
|
||||||
proxy.$modal.msgSuccess('保存成功');
|
|
||||||
nextId.value = 1;
|
|
||||||
// 保存成功后刷新列表,确保后端返回的数据带 requestId
|
|
||||||
getListInfo(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// 不需要再添加空行,保存成功后由 getListInfo 处理
|
|
||||||
}
|
}
|
||||||
adviceQueryParams.value.adviceType = undefined;
|
adviceQueryParams.value.adviceType = undefined;
|
||||||
}
|
}
|
||||||
@@ -1471,13 +1429,12 @@ function handleSaveBatch() {
|
|||||||
if (row) row.isEdit = false;
|
if (row) row.isEdit = false;
|
||||||
});
|
});
|
||||||
getListInfo(false);
|
getListInfo(false);
|
||||||
nextId.value = 1;
|
nextId.value == 1;
|
||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
isSaving.value = false;
|
isSaving.value = false;
|
||||||
proxy.$modal.msgError(error?.msg || '保存失败,请重试');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1605,21 +1562,17 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
// 🔥 新版组件已经预处理了数据,优先使用 mergedDetail
|
// 🔥 新版组件已经预处理了数据,优先使用 mergedDetail
|
||||||
const mergedDetail = item.mergedDetail || {
|
const mergedDetail = item.mergedDetail || {
|
||||||
...(item.orderDetailInfos || {}),
|
...(item.orderDetailInfos || {}),
|
||||||
adviceName: item.orderDefinitionName || item.orderDetailInfos?.adviceName || '未知项目',
|
adviceName: item.orderDetailInfos?.adviceName || item.orderDefinitionName || '未知项目',
|
||||||
adviceType: item.orderDetailInfos?.adviceType,
|
adviceType: item.orderDetailInfos?.adviceType,
|
||||||
adviceDefinitionId: item.orderDefinitionId || item.orderDetailInfos?.adviceDefinitionId,
|
adviceDefinitionId: item.orderDefinitionId || item.orderDetailInfos?.adviceDefinitionId,
|
||||||
quantity: item.quantity,
|
quantity: item.quantity,
|
||||||
unitCode: item.unitCode || item.orderDetailInfos?.unitCode,
|
unitCode: item.unitCode || item.orderDetailInfos?.unitCode,
|
||||||
unitCodeName: item.unitCodeName,
|
unitCodeName: item.unitCodeName,
|
||||||
// 🔧 Bug #403 修复:dose/doseQuantity/dispensePerDuration 需用 null 检查,
|
dose: item.dose || item.orderDetailInfos?.dose,
|
||||||
// 避免组套中值为 null 时回退到医嘱库的 orderDetailInfos
|
|
||||||
dose: item.dose !== undefined && item.dose !== null ? item.dose : item.orderDetailInfos?.dose,
|
|
||||||
rateCode: item.rateCode || item.orderDetailInfos?.rateCode,
|
rateCode: item.rateCode || item.orderDetailInfos?.rateCode,
|
||||||
methodCode: item.methodCode || item.orderDetailInfos?.methodCode,
|
methodCode: item.methodCode || item.orderDetailInfos?.methodCode,
|
||||||
dispensePerDuration: item.dispensePerDuration !== undefined && item.dispensePerDuration !== null
|
dispensePerDuration: item.dispensePerDuration || item.orderDetailInfos?.dispensePerDuration,
|
||||||
? item.dispensePerDuration : item.orderDetailInfos?.dispensePerDuration,
|
doseQuantity: item.doseQuantity,
|
||||||
doseQuantity: item.doseQuantity !== undefined && item.doseQuantity !== null
|
|
||||||
? item.doseQuantity : item.orderDetailInfos?.doseQuantity,
|
|
||||||
inventoryList: item.orderDetailInfos?.inventoryList || [],
|
inventoryList: item.orderDetailInfos?.inventoryList || [],
|
||||||
priceList: item.orderDetailInfos?.priceList || [],
|
priceList: item.orderDetailInfos?.priceList || [],
|
||||||
partPercent: item.orderDetailInfos?.partPercent || 1,
|
partPercent: item.orderDetailInfos?.partPercent || 1,
|
||||||
@@ -1638,15 +1591,20 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
setValue(mergedDetail);
|
setValue(mergedDetail);
|
||||||
|
|
||||||
// 创建新的处方项目
|
// 创建新的处方项目
|
||||||
// 🔧 Bug #403 修复:关键字段使用 null-safe 回退到 mergedDetail(已由 setValue 填充完整数据)
|
|
||||||
// 先取 setValue 填充的行数据作为基础
|
|
||||||
const baseRow = prescriptionList.value[rowIndex.value];
|
|
||||||
const newRow = {
|
const newRow = {
|
||||||
...baseRow,
|
...prescriptionList.value[rowIndex.value],
|
||||||
patientId: patientInfo.value.patientId,
|
patientId: patientInfo.value.patientId,
|
||||||
encounterId: patientInfo.value.encounterId,
|
encounterId: patientInfo.value.encounterId,
|
||||||
accountId: accountId.value,
|
accountId: accountId.value,
|
||||||
|
quantity: item.quantity,
|
||||||
|
methodCode: item.methodCode,
|
||||||
|
rateCode: item.rateCode,
|
||||||
|
dispensePerDuration: item.dispensePerDuration,
|
||||||
|
dose: item.dose,
|
||||||
|
doseQuantity: item.doseQuantity,
|
||||||
executeNum: 1,
|
executeNum: 1,
|
||||||
|
unitCode: item.unitCode,
|
||||||
|
unitCode_dictText: item.unitCodeName || '',
|
||||||
statusEnum: 1,
|
statusEnum: 1,
|
||||||
orgId: resolveOrgId(item.orderDetailInfos?.orgId || mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '',
|
orgId: resolveOrgId(item.orderDetailInfos?.orgId || mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '',
|
||||||
// 🔧 修复:同时保存 orgName,确保树匹配不到时仍有中文名称可显示
|
// 🔧 修复:同时保存 orgName,确保树匹配不到时仍有中文名称可显示
|
||||||
@@ -1655,33 +1613,19 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
conditionId: conditionId.value,
|
conditionId: conditionId.value,
|
||||||
conditionDefinitionId: conditionDefinitionId.value,
|
conditionDefinitionId: conditionDefinitionId.value,
|
||||||
encounterDiagnosisId: encounterDiagnosisId.value,
|
encounterDiagnosisId: encounterDiagnosisId.value,
|
||||||
therapyEnum: baseRow?.therapyEnum || '1',
|
therapyEnum: prescriptionList.value[rowIndex.value]?.therapyEnum || '1',
|
||||||
};
|
};
|
||||||
// 覆盖关键字段:优先使用 item 的值,其次 mergedDetail(已由 setValue 填充),最后 baseRow
|
|
||||||
newRow.quantity = item.quantity ?? mergedDetail.quantity ?? baseRow.quantity;
|
|
||||||
newRow.methodCode = item.methodCode ?? mergedDetail.methodCode ?? baseRow.methodCode;
|
|
||||||
newRow.rateCode = item.rateCode ?? mergedDetail.rateCode ?? baseRow.rateCode;
|
|
||||||
newRow.dispensePerDuration = item.dispensePerDuration ?? mergedDetail.dispensePerDuration ?? baseRow.dispensePerDuration;
|
|
||||||
newRow.dose = item.dose ?? mergedDetail.dose ?? baseRow.dose;
|
|
||||||
newRow.doseQuantity = item.doseQuantity ?? mergedDetail.doseQuantity ?? baseRow.doseQuantity;
|
|
||||||
newRow.unitCode = item.unitCode ?? mergedDetail.unitCode ?? baseRow.unitCode;
|
|
||||||
newRow.unitCode_dictText = item.unitCodeName || mergedDetail.unitCodeName || baseRow.unitCode_dictText || '';
|
|
||||||
|
|
||||||
// 计算价格和总量
|
// 计算价格和总量
|
||||||
// 🔧 Bug #403 修复:使用 newRow.unitCode(已由 setValue 填充)而非 item.unitCode
|
const unitInfo = unitCodeList.value.find((k) => k.value == item.unitCode);
|
||||||
// 使用 ?? 替代 || 计算 partPercent,确保值为 0 时不会被错误替换
|
|
||||||
const finalUnitCode = newRow.unitCode;
|
|
||||||
const unitInfo = unitCodeList.value.find((k) => k.value == finalUnitCode);
|
|
||||||
const finalQuantity = newRow.quantity;
|
|
||||||
const partPercent = item.orderDetailInfos?.partPercent ?? mergedDetail.partPercent ?? baseRow.partPercent ?? 1;
|
|
||||||
if (unitInfo && unitInfo.type == 'minUnit') {
|
if (unitInfo && unitInfo.type == 'minUnit') {
|
||||||
newRow.price = newRow.minUnitPrice;
|
newRow.price = newRow.minUnitPrice;
|
||||||
newRow.totalPrice = ((finalQuantity || 0) * newRow.minUnitPrice).toFixed(6);
|
newRow.totalPrice = (item.quantity * newRow.minUnitPrice).toFixed(6);
|
||||||
newRow.minUnitQuantity = finalQuantity || 0;
|
newRow.minUnitQuantity = item.quantity;
|
||||||
} else {
|
} else {
|
||||||
newRow.price = newRow.unitPrice;
|
newRow.price = newRow.unitPrice;
|
||||||
newRow.totalPrice = ((finalQuantity || 0) * newRow.unitPrice).toFixed(6);
|
newRow.totalPrice = (item.quantity * newRow.unitPrice).toFixed(6);
|
||||||
newRow.minUnitQuantity = (finalQuantity || 0) * partPercent;
|
newRow.minUnitQuantity = item.quantity * (item.orderDetailInfos?.partPercent || mergedDetail.partPercent || 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
newRow.contentJson = JSON.stringify(newRow);
|
newRow.contentJson = JSON.stringify(newRow);
|
||||||
|
|||||||
@@ -481,43 +481,12 @@ watch(
|
|||||||
(visible) => {
|
(visible) => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
executeTime.value = formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss');
|
executeTime.value = formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss');
|
||||||
// 弹窗打开时重新加载科室和位置选项,确保数据最新
|
|
||||||
loadDepartmentOptions();
|
|
||||||
getDiseaseInitLoc(16);
|
|
||||||
} else {
|
} else {
|
||||||
resetData();
|
resetData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// 监听科室选项加载完成,为已添加的诊疗项目设置默认执行科室
|
|
||||||
watch(
|
|
||||||
() => departmentOptions.value,
|
|
||||||
(depts) => {
|
|
||||||
if (!depts || depts.length === 0) return;
|
|
||||||
feeItemsList.value.forEach(item => {
|
|
||||||
if (item.adviceType === 3 && !item.positionId) {
|
|
||||||
const patientOrgId = props.patientInfo.organizationId;
|
|
||||||
const matched = depts.find(d => String(d.id) === String(patientOrgId));
|
|
||||||
item.positionId = matched ? String(matched.id) : String(depts[0].id);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 监听位置选项加载完成,为已添加的耗材项目设置默认位置
|
|
||||||
watch(
|
|
||||||
() => locationOptions.value,
|
|
||||||
(locs) => {
|
|
||||||
if (!locs || locs.length === 0) return;
|
|
||||||
feeItemsList.value.forEach(item => {
|
|
||||||
if (item.adviceType === 2 && !item.positionId) {
|
|
||||||
item.positionId = String(locs[0].value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 加载科室选项
|
// 加载科室选项
|
||||||
function loadDepartmentOptions() {
|
function loadDepartmentOptions() {
|
||||||
getOrgList()
|
getOrgList()
|
||||||
@@ -558,27 +527,23 @@ function getDiseaseInitLoc() {
|
|||||||
locationOptions.value = [];
|
locationOptions.value = [];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 下拉框模糊搜索过滤(自定义filter-method,配合element-plus filterable使用)
|
// 下拉框模糊搜索过滤
|
||||||
function filterOptions(val, row, optionsKey) {
|
function filterOptions(val, row, optionsKey) {
|
||||||
const key = row.adviceDefinitionId + '_' + optionsKey;
|
const key = row.adviceDefinitionId + '_' + optionsKey;
|
||||||
if (!val || val.trim() === '') {
|
filterKeywords.value[key] = val;
|
||||||
delete filterKeywords.value[key];
|
|
||||||
} else {
|
|
||||||
filterKeywords.value[key] = val.toLowerCase();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
function getFilteredOptions(row, optionsKey) {
|
function getFilteredOptions(row, optionsKey) {
|
||||||
const key = row.adviceDefinitionId + '_' + optionsKey;
|
const key = row.adviceDefinitionId + '_' + optionsKey;
|
||||||
const keyword = filterKeywords.value[key];
|
const keyword = filterKeywords.value[key];
|
||||||
const options = optionsKey === 'departmentOptions' ? departmentOptions.value : locationOptions.value;
|
const options = optionsKey === 'departmentOptions' ? departmentOptions.value : locationOptions.value;
|
||||||
if (!keyword) {
|
if (!keyword || keyword.trim() === '') {
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
const lower = keyword.toLowerCase();
|
||||||
return options.filter(item => {
|
return options.filter(item => {
|
||||||
const name = (item.name || item.label || '').toLowerCase();
|
const name = (item.name || item.label || '').toLowerCase();
|
||||||
const id = String(item.id || item.value || '').toLowerCase();
|
const id = String(item.id || item.value || '').toLowerCase();
|
||||||
const py = (item.pyStr || '').toLowerCase();
|
return name.includes(lower) || id.includes(lower);
|
||||||
return name.includes(keyword) || id.includes(keyword) || py.includes(keyword);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// 获取组套类型文本
|
// 获取组套类型文本
|
||||||
@@ -588,9 +553,9 @@ function getItemType_Text(type) {
|
|||||||
}
|
}
|
||||||
function getUnitCodeOptions(row) {
|
function getUnitCodeOptions(row) {
|
||||||
const unitCodes = [
|
const unitCodes = [
|
||||||
{ code: String(row.unitCode), codeText: row.unitCode_dictText },
|
{ code: row.unitCode, codeText: row.unitCode_dictText },
|
||||||
{ code: String(row.minUnitCode), codeText: row.minUnitCode_dictText },
|
{ code: row.minUnitCode, codeText: row.minUnitCode_dictText },
|
||||||
].filter(item => item.code);
|
];
|
||||||
// 使用 Set 来跟踪已经存在的 code
|
// 使用 Set 来跟踪已经存在的 code
|
||||||
const seenCodes = new Set();
|
const seenCodes = new Set();
|
||||||
const uniqueUnitCodes = unitCodes.filter((item) => {
|
const uniqueUnitCodes = unitCodes.filter((item) => {
|
||||||
@@ -610,11 +575,11 @@ function unitCodeChange(row) {
|
|||||||
// 获取价格
|
// 获取价格
|
||||||
const price = row.priceList?.[0]?.price || 0;
|
const price = row.priceList?.[0]?.price || 0;
|
||||||
|
|
||||||
// 根据选择的单位调整单价(统一用字符串比较)
|
// 根据选择的单位调整单价
|
||||||
if (String(row.selectUnitCode) === String(row.unitCode)) {
|
if (row.selectUnitCode === row.unitCode) {
|
||||||
// 如果选择的是大单位 (如 "盒")
|
// 如果选择的是大单位 (如 "盒")
|
||||||
row.unitPrice = price.toFixed(6); // 单价就是原价
|
row.unitPrice = price.toFixed(6); // 单价就是原价
|
||||||
} else if (String(row.selectUnitCode) === String(row.minUnitCode)) {
|
} else if (row.selectUnitCode === row.minUnitCode) {
|
||||||
// 如果选择的是小单位 (如 "个")
|
// 如果选择的是小单位 (如 "个")
|
||||||
row.unitPrice = (price / (row.partPercent || 1)).toFixed(6); // 单价 = 原价 / 拆零比
|
row.unitPrice = (price / (row.partPercent || 1)).toFixed(6); // 单价 = 原价 / 拆零比
|
||||||
}
|
}
|
||||||
@@ -806,32 +771,15 @@ function openGroupSetDialog() {
|
|||||||
|
|
||||||
function loadGroupSets() {
|
function loadGroupSets() {
|
||||||
groupSetLoading.value = true;
|
groupSetLoading.value = true;
|
||||||
const params = { organizationId: orgId.value };
|
getOrderGroup({ organizationId: orgId.value })
|
||||||
// 传递搜索关键字,后端 /group-package-for-order 虽不直接支持 searchKey,
|
|
||||||
// 但保持参数传递以便后续扩展
|
|
||||||
if (groupSetSearchText.value && groupSetSearchText.value.trim()) {
|
|
||||||
params.searchKey = groupSetSearchText.value.trim();
|
|
||||||
}
|
|
||||||
getOrderGroup(params)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
const data = res?.data || {};
|
const data = res?.data || {};
|
||||||
let rawList = [];
|
|
||||||
if (groupSetRange.value === 1) {
|
if (groupSetRange.value === 1) {
|
||||||
rawList = data.personalList || [];
|
groupSetList.value = data.personalList || [];
|
||||||
} else if (groupSetRange.value === 2) {
|
} else if (groupSetRange.value === 2) {
|
||||||
rawList = data.organizationList || [];
|
groupSetList.value = data.organizationList || [];
|
||||||
} else {
|
} else {
|
||||||
rawList = data.hospitalList || [];
|
groupSetList.value = data.hospitalList || [];
|
||||||
}
|
|
||||||
// 客户端过滤:根据搜索关键字过滤组套名称
|
|
||||||
const keyword = groupSetSearchText.value?.trim()?.toLowerCase();
|
|
||||||
if (keyword) {
|
|
||||||
groupSetList.value = rawList.filter(item => {
|
|
||||||
const name = (item.name || item.Name || '').toLowerCase();
|
|
||||||
return name.includes(keyword);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
groupSetList.value = rawList;
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
|
|||||||
@@ -302,29 +302,6 @@ function getSelectRows() {
|
|||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTableRef(index) {
|
|
||||||
return proxy.$refs['tableRef' + index]?.[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectAllRows() {
|
|
||||||
prescriptionList.value.forEach((item, index) => {
|
|
||||||
const tableRef = getTableRef(index);
|
|
||||||
if (!tableRef) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
item.forEach((row) => {
|
|
||||||
tableRef.toggleRowSelection(row, true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearSelection() {
|
|
||||||
prescriptionList.value.forEach((item, index) => {
|
|
||||||
getTableRef(index)?.clearSelection();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRateChange(value, item, row) {
|
function handleRateChange(value, item, row) {
|
||||||
// 拼接当前选中时间
|
// 拼接当前选中时间
|
||||||
if (value) {
|
if (value) {
|
||||||
@@ -342,8 +319,6 @@ function handleRateChange(value, item, row) {
|
|||||||
defineExpose({
|
defineExpose({
|
||||||
handleGetPrescription,
|
handleGetPrescription,
|
||||||
handleMedicineSummary,
|
handleMedicineSummary,
|
||||||
selectAllRows,
|
|
||||||
clearSelection,
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -66,21 +66,13 @@ const props = defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 1,
|
default: 1,
|
||||||
},
|
},
|
||||||
therapyEnum: {
|
|
||||||
type: Number,
|
|
||||||
default: undefined,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handleGetPrescription();
|
handleGetPrescription();
|
||||||
function handleGetPrescription() {
|
function handleGetPrescription() {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(',');
|
let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(',');
|
||||||
const params = {};
|
getMedicineSummary({}).then((res) => {
|
||||||
if (props.therapyEnum !== undefined) {
|
|
||||||
params.therapyEnum = props.therapyEnum;
|
|
||||||
}
|
|
||||||
getMedicineSummary(params).then((res) => {
|
|
||||||
medicineSummaryFormList.value = res.data.records;
|
medicineSummaryFormList.value = res.data.records;
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -69,11 +69,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="descriptions-item-label">全选:</span>
|
<span class="descriptions-item-label">全选:</span>
|
||||||
<el-switch
|
<el-switch v-model="chooseAll" @change="handelSwicthChange" />
|
||||||
v-model="chooseAll"
|
|
||||||
:disabled="isDetails != '1'"
|
|
||||||
@change="handelSwicthChange"
|
|
||||||
/>
|
|
||||||
<el-button class="ml20 mr20" type="primary" @click="handleExecute"> 汇总领药 </el-button>
|
<el-button class="ml20 mr20" type="primary" @click="handleExecute"> 汇总领药 </el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -85,7 +81,7 @@
|
|||||||
:deadline="deadline"
|
:deadline="deadline"
|
||||||
:therapyEnum="therapyEnum"
|
:therapyEnum="therapyEnum"
|
||||||
/>
|
/>
|
||||||
<SummaryMedicineList v-else :therapyEnum="therapyEnum" />
|
<SummaryMedicineList v-else />
|
||||||
<!-- <el-tabs v-model="activeName" class="demo-tabs centered-tabs" @tab-change="handleClick">
|
<!-- <el-tabs v-model="activeName" class="demo-tabs centered-tabs" @tab-change="handleClick">
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
v-for="tab in prescriptionTabs"
|
v-for="tab in prescriptionTabs"
|
||||||
@@ -164,31 +160,24 @@ function handleClick(tabName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleGetPrescription() {
|
function handleGetPrescription() {
|
||||||
chooseAll.value = false;
|
prescriptionRefs.value.handleGetPrescription();
|
||||||
prescriptionRefs.value?.handleGetPrescription();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handelSwicthChange(value) {
|
function handelSwicthChange() {
|
||||||
if (!prescriptionRefs.value) {
|
if (chooseAll.value) {
|
||||||
chooseAll.value = false;
|
proxy.$refs['prescriptionRefs'].selectAllRows();
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (value) {
|
|
||||||
prescriptionRefs.value.selectAllRows();
|
|
||||||
} else {
|
} else {
|
||||||
prescriptionRefs.value.clearSelection();
|
proxy.$refs['prescriptionRefs'].clearSelection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleRadioChange(value) {
|
function handleRadioChange(value) {
|
||||||
chooseAll.value = false;
|
|
||||||
if (value == '1') {
|
if (value == '1') {
|
||||||
handleGetPrescription();
|
handleGetPrescription();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTherapyChange() {
|
function handleTherapyChange() {
|
||||||
chooseAll.value = false;
|
|
||||||
handleGetPrescription();
|
handleGetPrescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,4 +216,4 @@ provide('handleGetPrescription', (value) => {
|
|||||||
:deep(.el-tabs__header) {
|
:deep(.el-tabs__header) {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -453,10 +453,6 @@ const loadPatientInfo = () => {
|
|||||||
interventionForm.value.startTime = dayjs(res.data.startTime).format(
|
interventionForm.value.startTime = dayjs(res.data.startTime).format(
|
||||||
'YYYY-MM-DD HH:mm:ss'
|
'YYYY-MM-DD HH:mm:ss'
|
||||||
);
|
);
|
||||||
} else if (res.data.inHosTime) {
|
|
||||||
interventionForm.value.startTime = dayjs(res.data.inHosTime).format(
|
|
||||||
'YYYY-MM-DD HH:mm:ss'
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -471,13 +471,11 @@ function handleExecute() {
|
|||||||
console.log(list, 'list');
|
console.log(list, 'list');
|
||||||
adviceExecute({ exeDate: exeDate.value, adviceExecuteDetailList: list }).then((res) => {
|
adviceExecute({ exeDate: exeDate.value, adviceExecuteDetailList: list }).then((res) => {
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
// 仅当选中医嘱中包含诊疗类医嘱(可能绑定耗材)时,才调用耗材批号匹配
|
// 仅当选中医嘱中包含耗材类医嘱时,才调用耗材批号匹配(排除纯药品医嘱场景)
|
||||||
// adviceTable 取值为 med_medication_request(药品)或 wor_service_request(诊疗/耗材)
|
const hasDevice = list.some((item) =>
|
||||||
// 原代码用 includes('device') 判断有误,两个表名均不含 "device" 字符串
|
String(item.adviceTable || '').includes('device'),
|
||||||
const hasServiceRequest = list.some((item) =>
|
|
||||||
String(item.adviceTable || '') === 'wor_service_request',
|
|
||||||
);
|
);
|
||||||
if (hasServiceRequest) {
|
if (hasDevice) {
|
||||||
lotNumberMatch({ encounterIdList: encounterIds }, { skipErrorMsg: true }).catch((error) => {
|
lotNumberMatch({ encounterIdList: encounterIds }, { skipErrorMsg: true }).catch((error) => {
|
||||||
console.warn('lotNumberMatch failed after adviceExecute:', error);
|
console.warn('lotNumberMatch failed after adviceExecute:', error);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -829,9 +829,7 @@
|
|||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</div>
|
</div>
|
||||||
<div style="padding: 10px">
|
<div style="padding: 10px">
|
||||||
<prescriptionlist :patientInfo="chargePatientInfo" ref="prescriptionRef"
|
<prescriptionlist v-if="showChargeDialog" :patientInfo="chargePatientInfo" ref="prescriptionRef" />
|
||||||
:generateSourceEnum="1"
|
|
||||||
:sourceBillNo="chargePatientInfo.sourceBillNo" />
|
|
||||||
<div class="overlay" v-if="disabled"></div>
|
<div class="overlay" v-if="disabled"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -874,59 +872,16 @@ import { Loading } from '@element-plus/icons-vue' // 🔧 新增:导入 Loadin
|
|||||||
import { getPrescriptionList } from '@/views/clinicmanagement/bargain/component/api'
|
import { getPrescriptionList } from '@/views/clinicmanagement/bargain/component/api'
|
||||||
|
|
||||||
// API 导入
|
// API 导入
|
||||||
import {
|
import { getSurgerySchedulePage, addSurgerySchedule, updateSurgerySchedule, deleteSurgerySchedule, getSurgeryScheduleDetail } from '@/api/surgicalschedule'
|
||||||
getSurgerySchedulePage,
|
import { listUser } from '@/api/system/user'
|
||||||
addSurgerySchedule,
|
import { deptTreeSelect } from '@/api/system/user'
|
||||||
updateSurgerySchedule,
|
import { listOperatingRoom } from '@/api/operatingroom'
|
||||||
deleteSurgerySchedule,
|
import { getSurgery} from '@/views/inpatientDoctor/home/components/applicationShow/api.js'
|
||||||
getSurgeryScheduleDetail
|
import { getTenantPage } from '@/api/system/tenant'
|
||||||
} from '@/api/surgicalschedule'
|
|
||||||
import { getSurgeryPage} from '@/views/inpatientDoctor/home/components/applicationShow/api.js'
|
|
||||||
import { getContract } from '@/views/inpatientDoctor/home/components/api.js'
|
import { getContract } from '@/views/inpatientDoctor/home/components/api.js'
|
||||||
import request from '@/utils/request'
|
|
||||||
import SurgeryCharge from '../charge/surgerycharge/index.vue'
|
import SurgeryCharge from '../charge/surgerycharge/index.vue'
|
||||||
import TemporaryMedical from './temporaryMedical.vue'
|
import TemporaryMedical from './temporaryMedical.vue'
|
||||||
|
|
||||||
// 静默获取字典列表(跳过拦截器错误提示,手术室护士等角色可能无此权限)
|
|
||||||
function getTenantPageSilent(query) {
|
|
||||||
return request({
|
|
||||||
url: '/system/tenant/page',
|
|
||||||
method: 'get',
|
|
||||||
params: query,
|
|
||||||
skipErrorMsg: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 静默获取科室树(跳过拦截器错误提示)
|
|
||||||
function deptTreeSelectSilent(params = {}) {
|
|
||||||
return request({
|
|
||||||
url: '/base-data-manage/organization/organization',
|
|
||||||
method: 'get',
|
|
||||||
params: { typeEnum: 2, ...params },
|
|
||||||
skipErrorMsg: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 静默获取用户列表(跳过拦截器错误提示)
|
|
||||||
function listUserSilent(query) {
|
|
||||||
return request({
|
|
||||||
url: '/base-data-manage/practitioner/user-practitioner-page',
|
|
||||||
method: 'get',
|
|
||||||
params: query,
|
|
||||||
skipErrorMsg: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 静默获取手术室列表(跳过拦截器错误提示)
|
|
||||||
function listOperatingRoomSilent(query) {
|
|
||||||
return request({
|
|
||||||
url: '/base-data-manage/operating-room/list',
|
|
||||||
method: 'get',
|
|
||||||
params: query,
|
|
||||||
skipErrorMsg: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance()
|
const { proxy } = getCurrentInstance()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
@@ -1155,7 +1110,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
// 加载卫生机构列表
|
// 加载卫生机构列表
|
||||||
function loadOrgList() {
|
function loadOrgList() {
|
||||||
getTenantPageSilent({ pageNo: 1, pageSize: 1000 })
|
getTenantPage({ pageNo: 1, pageSize: 1000 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const records = res.data?.records || res.data || []
|
const records = res.data?.records || res.data || []
|
||||||
@@ -1175,7 +1130,7 @@ function loadOrgList() {
|
|||||||
|
|
||||||
// 加载科室列表
|
// 加载科室列表
|
||||||
function loadDeptList() {
|
function loadDeptList() {
|
||||||
deptTreeSelectSilent()
|
deptTreeSelect()
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const tree = res.data?.records || res.data || []
|
const tree = res.data?.records || res.data || []
|
||||||
@@ -1195,7 +1150,7 @@ function loadDeptList() {
|
|||||||
|
|
||||||
// 加载医生列表
|
// 加载医生列表
|
||||||
function loadDoctorList() {
|
function loadDoctorList() {
|
||||||
listUserSilent({ pageNo: 1, pageSize: 1000 })
|
listUser({ pageNo: 1, pageSize: 1000 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const records = res.data?.records || []
|
const records = res.data?.records || []
|
||||||
@@ -1215,7 +1170,7 @@ function loadDoctorList() {
|
|||||||
|
|
||||||
// 加载护士列表
|
// 加载护士列表
|
||||||
function loadNurseList() {
|
function loadNurseList() {
|
||||||
listUserSilent({ pageNo: 1, pageSize: 1000 })
|
listUser({ pageNo: 1, pageSize: 1000 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const records = res.data?.records || []
|
const records = res.data?.records || []
|
||||||
@@ -1235,7 +1190,7 @@ function loadNurseList() {
|
|||||||
|
|
||||||
// 加载手术室列表
|
// 加载手术室列表
|
||||||
function loadOperatingRoomList() {
|
function loadOperatingRoomList() {
|
||||||
listOperatingRoomSilent({ pageNo: 1, pageSize: 1000, statusEnum: 1 })
|
listOperatingRoom({ pageNo: 1, pageSize: 1000, statusEnum: 1 })
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const records = res.data?.records || []
|
const records = res.data?.records || []
|
||||||
@@ -1433,8 +1388,8 @@ async function handleChargeCharge(row) {
|
|||||||
orgId: userStore.organizationId || userStore.orgId || userStore.tenantId || 1,
|
orgId: userStore.organizationId || userStore.orgId || userStore.tenantId || 1,
|
||||||
// 添加账户ID
|
// 添加账户ID
|
||||||
accountId: accountId,
|
accountId: accountId,
|
||||||
// 添加手术单号用于关联对应的手术医嘱
|
// 添加手术申请单号用于追溯
|
||||||
sourceBillNo: row.operCode,
|
sourceBillNo: row.applyId,
|
||||||
//添加计费标志手术计费
|
//添加计费标志手术计费
|
||||||
generateSourceEnum: 6
|
generateSourceEnum: 6
|
||||||
}
|
}
|
||||||
@@ -1461,10 +1416,12 @@ function closeChargeDialog() {
|
|||||||
if (prescriptionRef.value && prescriptionRef.value.closeAllPopovers) {
|
if (prescriptionRef.value && prescriptionRef.value.closeAllPopovers) {
|
||||||
prescriptionRef.value.closeAllPopovers()
|
prescriptionRef.value.closeAllPopovers()
|
||||||
}
|
}
|
||||||
// 清空数据,避免下次打开时使用缓存
|
// 等 Vue 完成 DOM 更新后再关闭弹窗,确保 popover 先消失
|
||||||
showChargeDialog.value = false
|
nextTick(() => {
|
||||||
chargePatientInfo.value = {}
|
showChargeDialog.value = false
|
||||||
chargeSurgeryInfo.value = {}
|
chargePatientInfo.value = {}
|
||||||
|
chargeSurgeryInfo.value = {}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔧 新增:标志位,用于区分是"打开"还是"刷新"
|
// 🔧 新增:标志位,用于区分是"打开"还是"刷新"
|
||||||
@@ -1493,8 +1450,7 @@ function handleMedicalAdvice(row) {
|
|||||||
role: userStore.roles[0],
|
role: userStore.roles[0],
|
||||||
effectiveOrgId : row.effectiveOrgId,
|
effectiveOrgId : row.effectiveOrgId,
|
||||||
orgId: userStore.orgId,
|
orgId: userStore.orgId,
|
||||||
positionId: userStore.orgId,
|
positionId: userStore.orgId
|
||||||
applyId: row.applyId // 手术申请单ID,用于过滤关联医嘱
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔧 关键修复:如果已有提交的医嘱数据,并且是同一个患者的就诊,则使用保存的数据
|
// 🔧 关键修复:如果已有提交的医嘱数据,并且是同一个患者的就诊,则使用保存的数据
|
||||||
@@ -1540,8 +1496,6 @@ 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) 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;
|
||||||
@@ -1794,18 +1748,16 @@ function handleQuoteBilling() {
|
|||||||
// 重新拉取计费药品数据
|
// 重新拉取计费药品数据
|
||||||
if (temporaryPatientInfo.value.visitId) {
|
if (temporaryPatientInfo.value.visitId) {
|
||||||
temporaryMedicalLoading.value = true // 🔧 新增:开始加载
|
temporaryMedicalLoading.value = true // 🔧 新增:开始加载
|
||||||
getPrescriptionList(temporaryPatientInfo.value.visitId, 6, temporaryPatientInfo.value.operCode).then((res) => {
|
getPrescriptionList(temporaryPatientInfo.value.visitId).then((res) => {
|
||||||
if (res.code === 200 && res.data) {
|
if (res.code === 200 && res.data) {
|
||||||
// 🔧 修复:先清空旧数据,避免数据累积
|
// 🔧 修复:先清空旧数据,避免数据累积
|
||||||
temporaryBillingMedicines.value = []
|
temporaryBillingMedicines.value = []
|
||||||
temporaryAdvices.value = []
|
temporaryAdvices.value = []
|
||||||
|
|
||||||
// 只保留药品类型(adviceType=1),过滤掉耗材(2)和诊疗项目(3)
|
// 🔧 修复:显示所有药品请求数据,不管有没有计费项目
|
||||||
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) return false;
|
|
||||||
// 过滤掉名称为空的项目
|
// 过滤掉名称为空的项目
|
||||||
const medicineName = item.adviceName || item.advice_name;
|
const medicineName = item.adviceName || item.advice_name;
|
||||||
return medicineName && medicineName.trim() !== '';
|
return medicineName && medicineName.trim() !== '';
|
||||||
@@ -2071,7 +2023,7 @@ function handleFindApply() {
|
|||||||
getSurgicalScheduleList()
|
getSurgicalScheduleList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取手术申请列表(用于”查找”弹窗)
|
// 获取手术申请列表(用于“查找”弹窗)
|
||||||
function getSurgicalScheduleList() {
|
function getSurgicalScheduleList() {
|
||||||
applyLoading.value = true
|
applyLoading.value = true
|
||||||
const params = { ...applyQueryParams }
|
const params = { ...applyQueryParams }
|
||||||
@@ -2080,7 +2032,8 @@ function getSurgicalScheduleList() {
|
|||||||
params.applyTimeEnd = params.applyTimeRange[1]
|
params.applyTimeEnd = params.applyTimeRange[1]
|
||||||
delete params.applyTimeRange
|
delete params.applyTimeRange
|
||||||
}
|
}
|
||||||
getSurgeryPage(params).then((res) => {
|
getSurgery(params).then((res) => {
|
||||||
|
// Check if data is nested under data.data or directly under data
|
||||||
const responseData = res.data.data || res.data
|
const responseData = res.data.data || res.data
|
||||||
applyList.value = responseData.records || []
|
applyList.value = responseData.records || []
|
||||||
applyTotal.value = responseData.total || 0
|
applyTotal.value = responseData.total || 0
|
||||||
@@ -2329,4 +2282,4 @@ function getRowClassName({ row, rowIndex }) {
|
|||||||
border-bottom: 1px solid #d9ecff !important;
|
border-bottom: 1px solid #d9ecff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@@ -312,13 +312,6 @@ const getMethodCodeDict = computed(() => {
|
|||||||
|
|
||||||
// 响应式数据 - isSigned 从父组件传入的 prop 初始化
|
// 响应式数据 - isSigned 从父组件传入的 prop 初始化
|
||||||
const isSigned = ref(props.isSignedProp)
|
const isSigned = ref(props.isSignedProp)
|
||||||
|
|
||||||
// 🔧 修复 Bug #446: 同步父组件 isSignedProp 的变化到本地 isSigned
|
|
||||||
// ref(props.isSignedProp) 只在初始化时读取一次,父组件后续更新不会自动同步
|
|
||||||
watch(() => props.isSignedProp, (newVal) => {
|
|
||||||
isSigned.value = newVal
|
|
||||||
})
|
|
||||||
|
|
||||||
const signatureTime = ref('')
|
const signatureTime = ref('')
|
||||||
const showSignDialog = ref(false)
|
const showSignDialog = ref(false)
|
||||||
const signPassword = ref('')
|
const signPassword = ref('')
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
-- Bug #434 修复:为 op_schedule 表添加 incision_level 字段
|
|
||||||
-- 手术安排表需要存储切口类型,以便在编辑弹窗中正确回显和保存
|
|
||||||
ALTER TABLE op_schedule ADD COLUMN IF NOT EXISTS incision_level INT2;
|
|
||||||
|
|
||||||
COMMENT ON COLUMN op_schedule.incision_level IS '手术切口等级 1-I级切口 2-II级切口 3-III级切口 4-IV级切口';
|
|
||||||
Reference in New Issue
Block a user