Compare commits
19 Commits
陈琳
...
c424a37ebd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c424a37ebd | ||
|
|
93fc43715f | ||
|
|
1459bae9d0 | ||
|
|
40a7e0c231 | ||
|
|
4263cbbd9d | ||
|
|
6100d585c0 | ||
|
|
7df3999917 | ||
|
|
b21d499f66 | ||
|
|
1476c406cf | ||
|
|
9843ff9c05 | ||
| a620f8da22 | |||
|
|
374658923d | ||
|
|
a81e7ec980 | ||
| 39fefe9e80 | |||
|
|
5a4c2b6354 | ||
|
|
6626c8f1cd | ||
|
|
e2f4996f47 | ||
|
|
37b57e8b12 | ||
|
|
4bd0d2dcc8 |
@@ -7,7 +7,6 @@ import com.core.common.utils.MessageUtils;
|
||||
import com.openhis.administration.domain.Location;
|
||||
import com.openhis.administration.domain.Organization;
|
||||
import com.openhis.administration.domain.OrganizationLocation;
|
||||
import com.openhis.workflow.domain.ActivityDefinition;
|
||||
import com.openhis.administration.mapper.OrganizationLocationMapper;
|
||||
import com.openhis.administration.service.ILocationService;
|
||||
import com.openhis.administration.service.IOrganizationLocationService;
|
||||
@@ -71,7 +70,6 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation
|
||||
// 获取科室下拉选列表
|
||||
List<Organization> organizationList = organizationService.getList(OrganizationType.DEPARTMENT.getValue(), null);
|
||||
List<OrgLocInitDto.departmentOption> organizationOptions = organizationList.stream()
|
||||
.filter(organization -> organization != null && organization.getName() != null)
|
||||
.map(organization -> new OrgLocInitDto.departmentOption(organization.getId(), organization.getName()))
|
||||
.collect(Collectors.toList());
|
||||
initDto.setLocationFormOptions(chargeItemStatusOptions).setDepartmentOptions(organizationOptions);
|
||||
@@ -133,18 +131,12 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation
|
||||
@Override
|
||||
public R<?> addOrEditOrgLoc(OrgLocQueryDto orgLocQueryDto) {
|
||||
|
||||
// Validate required fields before processing
|
||||
if (orgLocQueryDto.getOrganizationId() == null) {
|
||||
return R.fail("请选择执行科室");
|
||||
}
|
||||
|
||||
OrganizationLocation orgLoc = new OrganizationLocation();
|
||||
BeanUtils.copyProperties(orgLocQueryDto, orgLoc);
|
||||
|
||||
Long activityDefinitionId = orgLoc.getActivityDefinitionId();
|
||||
ActivityDefinition activityDef = activityDefinitionId != null
|
||||
? activityDefinitionMapper.selectById(activityDefinitionId) : null;
|
||||
String activityName = activityDef != null ? activityDef.getName() : "";
|
||||
String activityName = activityDefinitionId != null
|
||||
? activityDefinitionMapper.selectById(activityDefinitionId).getName() : "";
|
||||
|
||||
List<OrganizationLocation> organizationLocationList =
|
||||
organizationLocationService.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getActivityDefinitionId());
|
||||
|
||||
@@ -274,8 +274,27 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
|
||||
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();
|
||||
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(
|
||||
new LambdaQueryWrapper<TriageQueueItem>()
|
||||
.eq(TriageQueueItem::getTenantId, tenantId)
|
||||
@@ -300,41 +319,14 @@ 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();
|
||||
} else 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果队列项存在且未完成,更新队列状态为已完成
|
||||
// 使用排除法而非白名单:只要不是"已完成"就可以完诊,覆盖跳过、等待等非标准流转状态
|
||||
if (queueItem != null &&
|
||||
!TriageQueueStatus.COMPLETED.getValue().equals(queueItem.getStatus())) {
|
||||
java.time.LocalDateTime nowLocal = java.time.LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
// 使用 LambdaUpdateWrapper 直接更新,确保 status 字段必定写入数据库
|
||||
boolean queueUpdate = triageQueueItemService.update(new LambdaUpdateWrapper<TriageQueueItem>()
|
||||
.eq(TriageQueueItem::getId, queueItem.getId())
|
||||
.set(TriageQueueItem::getStatus, TriageQueueStatus.COMPLETED.getValue())
|
||||
.set(TriageQueueItem::getUpdateTime, nowLocal));
|
||||
if (!queueUpdate) {
|
||||
log.error("完诊:triage_queue_item 状态更新失败,queueItemId={}", queueItem.getId());
|
||||
}
|
||||
queueItem.setStatus(TriageQueueStatus.COMPLETED.getValue());
|
||||
queueItem.setUpdateTime(nowLocal);
|
||||
triageQueueItemService.updateById(queueItem);
|
||||
} else if (queueItem == null) {
|
||||
log.error("完诊:未找到任何 triage_queue_item 记录,encounterId={}, tenantId={}",
|
||||
encounterId, tenantId);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.openhis.web.doctorstation.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import lombok.Data;
|
||||
@@ -56,7 +55,6 @@ public class InfectiousDiseaseReportDto {
|
||||
private String sex;
|
||||
|
||||
/** 出生日期 */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private Date birthday;
|
||||
|
||||
/** 实足年龄 */
|
||||
|
||||
@@ -17,9 +17,6 @@ import com.openhis.common.constant.PromptMsgConstant;
|
||||
import com.openhis.common.enums.*;
|
||||
import com.openhis.common.utils.EnumUtils;
|
||||
import com.openhis.common.utils.HisQueryUtils;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import com.openhis.workflow.domain.InventoryItem;
|
||||
import com.openhis.workflow.service.IInventoryItemService;
|
||||
import com.openhis.web.basedatamanage.dto.LocationDto;
|
||||
import com.openhis.web.common.dto.UnitDto;
|
||||
import com.openhis.web.inventorymanage.appservice.IProductTransferAppService;
|
||||
@@ -60,9 +57,6 @@ public class ProductTransferAppServiceImpl implements IProductTransferAppService
|
||||
@Autowired
|
||||
private IPractitionerService practitionerService;
|
||||
|
||||
@Autowired
|
||||
private IInventoryItemService inventoryItemService;
|
||||
|
||||
/**
|
||||
* 商品调拨页面初始化
|
||||
*
|
||||
@@ -202,23 +196,6 @@ public class ProductTransferAppServiceImpl implements IProductTransferAppService
|
||||
@Override
|
||||
public R<?> addOrEditBatchTransferReceipt(List<ProductTransferDto> productTransferDtoList, Boolean flag) {
|
||||
|
||||
// 校验调拨数量:必须 > 0 且不超过源库存数量(从数据库查实时库存)
|
||||
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
|
||||
for (ProductTransferDto dto : productTransferDtoList) {
|
||||
if (dto.getItemQuantity() == null || dto.getItemQuantity().compareTo(java.math.BigDecimal.ZERO) <= 0) {
|
||||
return R.fail("调拨数量必须大于0");
|
||||
}
|
||||
// 查询该药品在源仓库的实时库存总量
|
||||
List<InventoryItem> inventoryList = inventoryItemService.selectInventoryByItemId(
|
||||
dto.getItemId(), dto.getLotNumber(), dto.getSourceLocationId(), tenantId);
|
||||
java.math.BigDecimal actualStock = inventoryList.stream()
|
||||
.map(InventoryItem::getQuantity)
|
||||
.reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
|
||||
if (dto.getItemQuantity().compareTo(actualStock) > 0) {
|
||||
return R.fail("调拨数量不可超出源库存数量(当前库存:" + actualStock + ")");
|
||||
}
|
||||
}
|
||||
|
||||
List<String> idList = new ArrayList<>();
|
||||
if (flag) {
|
||||
// 批量保存按钮
|
||||
@@ -332,22 +309,6 @@ public class ProductTransferAppServiceImpl implements IProductTransferAppService
|
||||
@Override
|
||||
public R<?> addOrEditTransferReceipt(List<ProductTransferDto> productTransferDtoList) {
|
||||
|
||||
// 校验调拨数量:必须 > 0 且不超过源库存数量(从数据库查实时库存)
|
||||
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
|
||||
for (ProductTransferDto dto : productTransferDtoList) {
|
||||
if (dto.getItemQuantity() == null || dto.getItemQuantity().compareTo(java.math.BigDecimal.ZERO) <= 0) {
|
||||
return R.fail("调拨数量必须大于0");
|
||||
}
|
||||
List<InventoryItem> inventoryList = inventoryItemService.selectInventoryByItemId(
|
||||
dto.getItemId(), dto.getLotNumber(), dto.getSourceLocationId(), tenantId);
|
||||
java.math.BigDecimal actualStock = inventoryList.stream()
|
||||
.map(InventoryItem::getQuantity)
|
||||
.reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
|
||||
if (dto.getItemQuantity().compareTo(actualStock) > 0) {
|
||||
return R.fail("调拨数量不可超出源库存数量(当前库存:" + actualStock + ")");
|
||||
}
|
||||
}
|
||||
|
||||
List<String> idList = new ArrayList<>();
|
||||
|
||||
// 单据号取得
|
||||
@@ -419,25 +380,6 @@ public class ProductTransferAppServiceImpl implements IProductTransferAppService
|
||||
*/
|
||||
@Override
|
||||
public R<?> submitApproval(String busNo) {
|
||||
// 提交前再次校验调拨数量(从数据库查实时库存)
|
||||
List<SupplyRequest> requestList = supplyRequestService.getSupplyByBusNo(busNo);
|
||||
if (requestList != null && !requestList.isEmpty()) {
|
||||
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
|
||||
for (SupplyRequest request : requestList) {
|
||||
if (request.getItemQuantity() == null || request.getItemQuantity().compareTo(java.math.BigDecimal.ZERO) <= 0) {
|
||||
return R.fail("调拨数量必须大于0,请检查后重新保存");
|
||||
}
|
||||
// 查询该药品在源仓库的实时库存总量
|
||||
List<InventoryItem> inventoryList = inventoryItemService.selectInventoryByItemId(
|
||||
request.getItemId(), request.getLotNumber(), request.getSourceLocationId(), tenantId);
|
||||
java.math.BigDecimal actualStock = inventoryList.stream()
|
||||
.map(InventoryItem::getQuantity)
|
||||
.reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add);
|
||||
if (request.getItemQuantity().compareTo(actualStock) > 0) {
|
||||
return R.fail("调拨数量不可超出源库存数量(当前库存:" + actualStock + "),请检查后重新保存");
|
||||
}
|
||||
}
|
||||
}
|
||||
// 单据提交审核
|
||||
boolean result = supplyRequestService.submitApproval(busNo);
|
||||
return result ? R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null))
|
||||
|
||||
@@ -43,19 +43,6 @@ public interface IRequestFormManageAppService {
|
||||
*/
|
||||
List<RequestFormQueryDto> getRequestForm(Long encounterId, String typeCode, String startDate, String endDate);
|
||||
|
||||
/**
|
||||
* 查询申请单(支持筛选+状态+关键字)
|
||||
*
|
||||
* @param encounterId 就诊id
|
||||
* @param typeCode 申请单类型
|
||||
* @param startDate 开始日期(可选,格式:yyyy-MM-dd)
|
||||
* @param endDate 结束日期(可选,格式:yyyy-MM-dd)
|
||||
* @param status 单据状态(可选)
|
||||
* @param keyword 关键字(可选,申请单号/项目名称模糊匹配)
|
||||
* @return 申请单列表
|
||||
*/
|
||||
List<RequestFormQueryDto> getRequestForm(Long encounterId, String typeCode, String startDate, String endDate, String status, String keyword);
|
||||
|
||||
/**
|
||||
* 分页查询申请单
|
||||
*
|
||||
|
||||
@@ -341,28 +341,6 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
||||
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 防重复保存:对新增医嘱进行去重,避免签发单条长期医嘱时产生重复记录
|
||||
Set<String> longUniqueKeySet = new HashSet<>();
|
||||
List<RegAdviceSaveDto> longUniqueList = new ArrayList<>();
|
||||
for (RegAdviceSaveDto adviceSaveDto : longInsertOrUpdateList) {
|
||||
String uniqueKey = adviceSaveDto.getPatientId() + "_"
|
||||
+ adviceSaveDto.getEncounterId() + "_"
|
||||
+ adviceSaveDto.getAdviceDefinitionId() + "_"
|
||||
+ adviceSaveDto.getDose() + "_"
|
||||
+ adviceSaveDto.getMethodCode() + "_"
|
||||
+ adviceSaveDto.getRateCode();
|
||||
if (DbOpType.INSERT.getCode().equals(adviceSaveDto.getDbOpType()) && longUniqueKeySet.contains(uniqueKey)) {
|
||||
log.warn("防重复保存:检测到重复长期医嘱,跳过保存 - patientId={}, encounterId={}, adviceDefinitionId={}, dose={}",
|
||||
adviceSaveDto.getPatientId(), adviceSaveDto.getEncounterId(),
|
||||
adviceSaveDto.getAdviceDefinitionId(), adviceSaveDto.getDose());
|
||||
continue;
|
||||
}
|
||||
longUniqueKeySet.add(uniqueKey);
|
||||
longUniqueList.add(adviceSaveDto);
|
||||
}
|
||||
log.info("防重复保存(长期):去重前{}条,去重后{}条", longInsertOrUpdateList.size(), longUniqueList.size());
|
||||
longInsertOrUpdateList = longUniqueList;
|
||||
|
||||
for (RegAdviceSaveDto regAdviceSaveDto : longInsertOrUpdateList) {
|
||||
boolean firstTimeSave = false;// 第一次保存
|
||||
longMedicationRequest = new MedicationRequest();
|
||||
@@ -428,29 +406,6 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
||||
.getValue().equals(e.getTherapyEnum())
|
||||
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 防重复保存:对新增医嘱进行去重
|
||||
Set<String> tempUniqueKeySet = new HashSet<>();
|
||||
List<RegAdviceSaveDto> tempUniqueList = new ArrayList<>();
|
||||
for (RegAdviceSaveDto adviceSaveDto : tempInsertOrUpdateList) {
|
||||
String uniqueKey = adviceSaveDto.getPatientId() + "_"
|
||||
+ adviceSaveDto.getEncounterId() + "_"
|
||||
+ adviceSaveDto.getAdviceDefinitionId() + "_"
|
||||
+ adviceSaveDto.getDose() + "_"
|
||||
+ adviceSaveDto.getMethodCode() + "_"
|
||||
+ adviceSaveDto.getRateCode();
|
||||
if (DbOpType.INSERT.getCode().equals(adviceSaveDto.getDbOpType()) && tempUniqueKeySet.contains(uniqueKey)) {
|
||||
log.warn("防重复保存:检测到重复临时医嘱,跳过保存 - patientId={}, encounterId={}, adviceDefinitionId={}, dose={}",
|
||||
adviceSaveDto.getPatientId(), adviceSaveDto.getEncounterId(),
|
||||
adviceSaveDto.getAdviceDefinitionId(), adviceSaveDto.getDose());
|
||||
continue;
|
||||
}
|
||||
tempUniqueKeySet.add(uniqueKey);
|
||||
tempUniqueList.add(adviceSaveDto);
|
||||
}
|
||||
log.info("防重复保存(临时):去重前{}条,去重后{}条", tempInsertOrUpdateList.size(), tempUniqueList.size());
|
||||
tempInsertOrUpdateList = tempUniqueList;
|
||||
|
||||
for (RegAdviceSaveDto regAdviceSaveDto : tempInsertOrUpdateList) {
|
||||
boolean firstTimeSave = false;// 第一次保存
|
||||
tempMedicationRequest = new MedicationRequest();
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -92,10 +91,8 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
||||
return R.fail("无待签发的医嘱,该申请单不可编辑");
|
||||
}
|
||||
} else {
|
||||
// 检查申请单号:JC(检查)+ Z(住院标识)+ yyMMdd(日期)+ 5位顺序号
|
||||
String dateStr = new java.text.SimpleDateFormat("yyMMdd").format(new Date());
|
||||
int seq = assignSeqUtil.getSeqNoByDay(AssignSeqEnum.CHECK_APPLY_NO.getPrefix());
|
||||
prescriptionNo = "JCZ" + dateStr + String.format("%05d", seq);
|
||||
// 诊疗处方号
|
||||
prescriptionNo = assignSeqUtil.getSeq(AssignSeqEnum.ACTIVITY_PSYCHOTROPIC_NO.getPrefix(), 8);
|
||||
}
|
||||
|
||||
// 当前时间
|
||||
@@ -431,28 +428,12 @@ public class RequestFormManageAppServiceImpl implements IRequestFormManageAppSer
|
||||
*/
|
||||
@Override
|
||||
public List<RequestFormQueryDto> getRequestForm(Long encounterId, String typeCode, String startDate, String endDate) {
|
||||
return getRequestForm(encounterId, typeCode, startDate, endDate, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询申请单(支持筛选+状态+关键字)
|
||||
*
|
||||
* @param encounterId 就诊id
|
||||
* @param typeCode 申请单类型
|
||||
* @param startDate 开始日期(可选,格式:yyyy-MM-dd)
|
||||
* @param endDate 结束日期(可选,格式:yyyy-MM-dd)
|
||||
* @param status 单据状态(可选)
|
||||
* @param keyword 关键字(可选,申请单号/项目名称模糊匹配)
|
||||
* @return 申请单列表
|
||||
*/
|
||||
@Override
|
||||
public List<RequestFormQueryDto> getRequestForm(Long encounterId, String typeCode, String startDate, String endDate, String status, String keyword) {
|
||||
// 检查参数
|
||||
if (encounterId == null) {
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
List<RequestFormQueryDto> requestFormList = requestFormManageAppMapper.getRequestForm(encounterId, typeCode, startDate, endDate, status, keyword);
|
||||
List<RequestFormQueryDto> requestFormList = requestFormManageAppMapper.getRequestForm(encounterId, typeCode, startDate, endDate,null,null);
|
||||
for (RequestFormQueryDto requestFormQueryDto : requestFormList) {
|
||||
// 查询处方详情
|
||||
List<RequestFormDetailQueryDto> requestFormDetail =
|
||||
|
||||
@@ -98,7 +98,6 @@ public class RequestFormManageController {
|
||||
* @param startDate 开始日期(可选,格式:yyyy-MM-dd)
|
||||
* @param endDate 结束日期(可选,格式:yyyy-MM-dd)
|
||||
* @param status 单据状态(可选)
|
||||
* @param keyword 关键字(可选,申请单号/检验项目模糊匹配)
|
||||
* @return 检验申请单
|
||||
*/
|
||||
@GetMapping(value = "/get-inspection")
|
||||
@@ -106,12 +105,11 @@ public class RequestFormManageController {
|
||||
@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) {
|
||||
@RequestParam(required = false) String status) {
|
||||
if (encounterId == null) {
|
||||
return R.fail("就诊ID不能为空");
|
||||
}
|
||||
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROOF.getCode(), startDate, endDate, status, keyword));
|
||||
return R.ok(iRequestFormManageAppService.getRequestForm(encounterId, ActivityDefCategory.PROOF.getCode(), startDate, endDate));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -100,7 +100,6 @@
|
||||
WHEN T1.context_enum = 6 AND T1.product_id = 0 AND T1.service_table = 'wor_service_request' THEN COALESCE(wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = 6 THEN T2."name"
|
||||
WHEN T1.context_enum = #{activity} AND T1.product_id = 0 AND T1.service_table = 'wor_service_request' THEN COALESCE(wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = #{activity} AND T1.service_table = 'wor_service_request' THEN COALESCE(T9.surgery_name, wsr.content_json::json->>'surgeryName', wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = #{activity} THEN COALESCE(wsr.content_json::json->>'surgeryName', wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = #{medication} THEN T3."name"
|
||||
WHEN T1.context_enum = #{device} THEN T4."name"
|
||||
@@ -226,7 +225,6 @@
|
||||
WHEN T1.context_enum = 6 AND T1.product_id = 0 AND T1.service_table = 'wor_service_request' THEN COALESCE(wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = 6 THEN T2."name"
|
||||
WHEN T1.context_enum = #{activity} AND T1.product_id = 0 AND T1.service_table = 'wor_service_request' THEN COALESCE(wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = #{activity} AND T1.service_table = 'wor_service_request' THEN COALESCE(T9.surgery_name, wsr.content_json::json->>'surgeryName', wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = #{activity} THEN COALESCE(wsr.content_json::json->>'surgeryName', wsr.content_json::json->>'adviceName', T2."name")
|
||||
WHEN T1.context_enum = #{medication} THEN T3."name"
|
||||
WHEN T1.context_enum = #{device} THEN T4."name"
|
||||
|
||||
@@ -541,9 +541,9 @@
|
||||
CI.service_id AS request_id,
|
||||
CI.service_id || '-ci-dev' AS unique_key,
|
||||
'' AS prescription_no,
|
||||
COALESCE(DR.requester_id, CI.enterer_id) AS requester_id,
|
||||
CI.enterer_id AS requester_id,
|
||||
CI.entered_date AS request_time,
|
||||
CASE WHEN COALESCE(DR.requester_id, CI.enterer_id) = #{practitionerId} THEN '1' ELSE '0' END AS biz_request_flag,
|
||||
CASE WHEN CI.enterer_id = #{practitionerId} THEN '1' ELSE '0' END AS biz_request_flag,
|
||||
DR.content_json AS content_json,
|
||||
NULL AS skin_test_flag,
|
||||
NULL AS inject_flag,
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
ae.priority_enum,
|
||||
ae.organization_id,
|
||||
ae.start_time AS in_hos_time,
|
||||
COALESCE(bed.start_time, ae.start_time) AS start_time,
|
||||
bed.start_time,
|
||||
bed.location_id AS bed_id,
|
||||
bed.location_name AS bed_name,
|
||||
house.location_id AS house_id,
|
||||
|
||||
@@ -12,24 +12,12 @@
|
||||
drf.desc_json,
|
||||
drf.requester_id,
|
||||
drf.create_time,
|
||||
ap.NAME AS patient_name,
|
||||
CASE MIN(wsr.status_enum)
|
||||
WHEN 1 THEN 0
|
||||
WHEN 2 THEN 1
|
||||
WHEN 3 THEN 4
|
||||
WHEN 4 THEN 4
|
||||
WHEN 5 THEN 5
|
||||
WHEN 6 THEN 5
|
||||
WHEN 7 THEN 5
|
||||
ELSE NULL
|
||||
END AS status
|
||||
ap.NAME AS patient_name
|
||||
FROM doc_request_form AS drf
|
||||
LEFT JOIN adm_encounter AS ae ON ae.ID = drf.encounter_id
|
||||
AND ae.delete_flag = '0'
|
||||
LEFT JOIN adm_patient AS ap ON ap.ID = ae.patient_id
|
||||
AND ap.delete_flag = '0'
|
||||
LEFT JOIN wor_service_request AS wsr ON wsr.prescription_no = drf.prescription_no
|
||||
AND wsr.delete_flag = '0'
|
||||
WHERE drf.delete_flag = '0'
|
||||
AND drf.encounter_id = #{encounterId}
|
||||
AND drf.type_code = #{typeCode}
|
||||
@@ -39,33 +27,6 @@
|
||||
<if test="endDate != null and endDate != ''">
|
||||
AND drf.create_time <= (#{endDate}::date + INTERVAL '1 day' - INTERVAL '1 second')
|
||||
</if>
|
||||
<if test="status != null and status != ''">
|
||||
AND CASE MIN(wsr.status_enum)
|
||||
WHEN 1 THEN 0
|
||||
WHEN 2 THEN 1
|
||||
WHEN 3 THEN 4
|
||||
WHEN 4 THEN 4
|
||||
WHEN 5 THEN 5
|
||||
WHEN 6 THEN 5
|
||||
WHEN 7 THEN 5
|
||||
ELSE NULL
|
||||
END = #{status}::integer
|
||||
</if>
|
||||
<if test="keyword != null and keyword != ''">
|
||||
AND (drf.prescription_no ILIKE '%' || #{keyword} || '%'
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM wor_service_request wsr2
|
||||
WHERE wsr2.prescription_no = drf.prescription_no
|
||||
AND wsr2.delete_flag = '0'
|
||||
AND wsr2.activity_id IN (
|
||||
SELECT id FROM wor_activity_definition wad
|
||||
WHERE wad.delete_flag = '0'
|
||||
AND wad.name ILIKE '%' || #{keyword} || '%'
|
||||
)
|
||||
))
|
||||
</if>
|
||||
GROUP BY drf.id, drf.encounter_id, drf.prescription_no, drf.name, drf.desc_json,
|
||||
drf.requester_id, drf.create_time, ap.name
|
||||
</select>
|
||||
|
||||
<select id="getRequestFormDetail" resultType="com.openhis.web.regdoctorstation.dto.RequestFormDetailQueryDto">
|
||||
|
||||
@@ -270,10 +270,6 @@ public enum AssignSeqEnum {
|
||||
* 诊疗处方号
|
||||
*/
|
||||
ACTIVITY_PSYCHOTROPIC_NO("62", "诊疗处方号", "PAR"),
|
||||
/**
|
||||
* 检查申请单号(住院)
|
||||
*/
|
||||
CHECK_APPLY_NO("72", "检查申请单号", "JCZ"),
|
||||
/**
|
||||
* b 病历文书
|
||||
*/
|
||||
|
||||
@@ -475,13 +475,8 @@ function calculateTotalPrice() {
|
||||
});
|
||||
totalPrice.value = sum.toFixed(2);
|
||||
// Bug #464: 零售价与诊疗子项合计总价实时同步
|
||||
const hasValidItem = treatmentItems.value.some(
|
||||
(item) => item.adviceDefinitionId && item.adviceDefinitionId !== ''
|
||||
);
|
||||
if (hasValidItem) {
|
||||
if (treatmentItems.value.length > 0 && treatmentItems.value[0].adviceDefinitionId !== '') {
|
||||
form.value.retailPrice = parseFloat(totalPrice.value);
|
||||
} else {
|
||||
form.value.retailPrice = undefined;
|
||||
}
|
||||
} catch (error) {
|
||||
totalPrice.value = '0.00';
|
||||
@@ -491,7 +486,7 @@ function calculateTotalPrice() {
|
||||
|
||||
// 添加表单项
|
||||
function addItem() {
|
||||
treatmentItems.value.push({ adviceDefinitionId: '', childrenRequestNum: 1, name: '', retailPrice: 0 });
|
||||
treatmentItems.value.push({ adviceDefinitionId: '', childrenRequestNum: 1, retailPrice: 0 });
|
||||
// 使用nextTick确保DOM更新后再计算
|
||||
nextTick(() => {
|
||||
calculateTotalPrice();
|
||||
@@ -652,15 +647,12 @@ async function submitForm() {
|
||||
form.value.ybMatchFlag ? (form.value.ybMatchFlag = 1) : (form.value.ybMatchFlag = 0);
|
||||
form.value.ruleId ? (form.value.ruleId = 1) : (form.value.ruleId = 0);
|
||||
form.value.childrenJson =
|
||||
treatmentItems.value.some((item) => item.adviceDefinitionId != '' && item.adviceDefinitionId)
|
||||
treatmentItems.value.length > 0 && treatmentItems.value[0].adviceDefinitionId != ''
|
||||
? JSON.stringify(treatmentItems.value)
|
||||
: undefined;
|
||||
// Bug #464 修复:零售价自动与诊疗子项合计总价同步
|
||||
// 当有子项时,零售价自动设置为子项合计总价
|
||||
const hasValidItem = treatmentItems.value.some(
|
||||
(item) => item.adviceDefinitionId && item.adviceDefinitionId !== ''
|
||||
);
|
||||
if (hasValidItem) {
|
||||
if (treatmentItems.value.length > 0 && treatmentItems.value[0].adviceDefinitionId != '') {
|
||||
form.value.retailPrice = parseFloat(totalPrice.value) || 0;
|
||||
}
|
||||
proxy.$refs['diagnosisTreatmentRef'].validate(async (valid) => {
|
||||
|
||||
@@ -69,14 +69,13 @@ const throttledGetList = throttle(
|
||||
watch(
|
||||
() => props.adviceQueryParams,
|
||||
(newValue) => {
|
||||
// 始终同步参数到 queryParams,避免弹窗打开时使用旧参数
|
||||
queryParams.value.searchKey = newValue?.searchKey;
|
||||
queryParams.value.adviceType = newValue?.adviceType;
|
||||
queryParams.value.categoryCode = newValue?.categoryCode;
|
||||
// 只有在弹窗打开时才触发 API 请求
|
||||
// 只有在弹窗打开时才响应 adviceQueryParams 的变化,避免选择项目后弹窗关闭时触发不必要的请求
|
||||
if (!props.popoverVisible) {
|
||||
return;
|
||||
}
|
||||
queryParams.value.searchKey = newValue?.searchKey;
|
||||
queryParams.value.adviceType = newValue?.adviceType;
|
||||
queryParams.value.categoryCode = newValue?.categoryCode;
|
||||
throttledGetList();
|
||||
},
|
||||
{ deep: true }
|
||||
|
||||
@@ -519,10 +519,9 @@
|
||||
>
|
||||
<template #append>
|
||||
<!-- 审核记录:查看/审核都展示,保证留痕可追溯 -->
|
||||
<!-- 修复:查看模式始终显示区块;审核模式始终显示区块(header + 空状态 或 timeline) -->
|
||||
<div
|
||||
class="audit-records-section"
|
||||
v-if="drawerMode === 'view' || drawerMode === 'audit'"
|
||||
v-if="drawerMode === 'view' || (drawerMode === 'audit' && auditRecords.length > 0)"
|
||||
>
|
||||
<h3 class="section-title">审核记录</h3>
|
||||
<el-timeline v-if="auditRecords.length > 0">
|
||||
|
||||
@@ -349,17 +349,11 @@ async function getList() {
|
||||
if (res.code == 200) {
|
||||
// 过滤掉中医诊断,只保留西医诊断
|
||||
form.value.diagnosisList = res.data.filter(item => item.typeName !== '中医诊断');
|
||||
// 为旧数据添加默认分类和selectedDiseases
|
||||
// 为旧数据添加默认分类
|
||||
form.value.diagnosisList.forEach(item => {
|
||||
if (!item.classification) {
|
||||
item.classification = '西医';
|
||||
}
|
||||
// 如果ybNo(诊断编码)符合传染病编码格式,添加到selectedDiseases
|
||||
if (item.ybNo && /^(01|02|03)/.test(item.ybNo)) {
|
||||
item.selectedDiseases = [item.ybNo];
|
||||
} else {
|
||||
item.selectedDiseases = item.selectedDiseases || [];
|
||||
}
|
||||
});
|
||||
emits('diagnosisSave', false);
|
||||
}
|
||||
@@ -691,78 +685,23 @@ async function handleFoodDiseasesCheck() {
|
||||
|
||||
/**
|
||||
* 传染病报告卡处理
|
||||
* 通过诊断名称自动识别并勾选传染病报告卡中的疾病
|
||||
* 通过诊断目录维护的'报卡类型'字段自动识别是否有需要填写的传染病报告卡
|
||||
* 如果有则弹出诊断对应需登记的报告卡界面
|
||||
*/
|
||||
function handleInfectiousDiseaseReport() {
|
||||
// 疾病名称到报卡编码的映射(根据传染病报告卡弹窗中的疾病列表)
|
||||
const diseaseNameToCode = {
|
||||
// 甲类
|
||||
'鼠疫': '0101',
|
||||
'霍乱': '0102',
|
||||
// 乙类
|
||||
'传染性非典型肺炎': '0201',
|
||||
'艾滋病': '0202',
|
||||
'病毒性肝炎': '0203',
|
||||
'脊髓灰质炎': '0204',
|
||||
'人感染高致病性禽流感': '0205',
|
||||
'麻疹': '0206',
|
||||
'流行性出血热': '0207',
|
||||
'狂犬病': '0208',
|
||||
'流行性乙型脑炎': '0209',
|
||||
'登革热': '0210',
|
||||
'炭疽': '0211',
|
||||
'细菌性和阿米巴性痢疾': '0212',
|
||||
'肺结核': '0213',
|
||||
'伤寒和副伤寒': '0214',
|
||||
'流行性脑脊髓膜炎': '0215',
|
||||
'百日咳': '0216',
|
||||
'白喉': '0217',
|
||||
'新生儿破伤风': '0218',
|
||||
'猩红热': '0219',
|
||||
'布鲁氏菌病': '0220',
|
||||
'淋病': '0221',
|
||||
'梅毒': '0222',
|
||||
'钩端螺旋体病': '0223',
|
||||
'血吸虫病': '0224',
|
||||
'疟疾': '0225',
|
||||
'新型冠状病毒肺炎': '0226',
|
||||
'甲型H1N1流感': '0227',
|
||||
'人感染H7N9禽流感': '0228',
|
||||
// 丙类
|
||||
'流行性感冒': '0301',
|
||||
'流行性腮腺炎': '0302',
|
||||
'风疹': '0303',
|
||||
'急性出血性结膜炎': '0304',
|
||||
'麻风病': '0305',
|
||||
'流行性和地方性斑疹伤寒': '0306',
|
||||
'黑热病': '0307',
|
||||
'包虫病': '0308',
|
||||
'丝虫病': '0309',
|
||||
'除霍乱/菌痢/伤寒副伤寒以外的感染性腹泻病': '0310',
|
||||
'其它感染性腹泻病': '0310',
|
||||
'手足口病': '0311',
|
||||
};
|
||||
// 查找所有有报卡类型的诊断(reportTypeCode不为空)
|
||||
const diagnosesWithReportType = form.value.diagnosisList.filter(d => d.reportTypeCode);
|
||||
|
||||
// 获取所有诊断名称对应的报卡编码
|
||||
const allSelectedDiseases = form.value.diagnosisList
|
||||
.map(d => diseaseNameToCode[d.name] || null)
|
||||
.filter(code => code);
|
||||
|
||||
if (allSelectedDiseases.length === 0) {
|
||||
if (diagnosesWithReportType.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 优先使用主诊断
|
||||
const mainDiagnosis = form.value.diagnosisList.find(d => d.maindiseFlag === 1);
|
||||
const firstDiagnosis = form.value.diagnosisList[0];
|
||||
|
||||
const diagnosisToShow = {
|
||||
...(mainDiagnosis || firstDiagnosis),
|
||||
selectedDiseases: allSelectedDiseases
|
||||
};
|
||||
// 优先使用主诊断,如果没有主诊断有报卡类型则使用第一个有报卡类型的诊断
|
||||
const mainDiagnosisWithReport = diagnosesWithReportType.find(d => d.maindiseFlag === 1);
|
||||
const targetDiagnosis = mainDiagnosisWithReport || diagnosesWithReportType[0];
|
||||
|
||||
// 弹出传染病报告卡弹窗
|
||||
proxy.$refs.infectiousDiseaseReportRef?.show(diagnosisToShow);
|
||||
proxy.$refs.infectiousDiseaseReportRef?.show(targetDiagnosis);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -875,8 +814,7 @@ form.value.diagnosisList.push({
|
||||
classification: '西医', // 默认为西医
|
||||
onsetDate: getCurrentDate(),
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: getCurrentDate(),
|
||||
selectedDiseases: data.ybNo ? [data.ybNo] : [], // 用于传染病报告卡自动勾选
|
||||
diagnosisTime: getCurrentDate()
|
||||
});
|
||||
|
||||
// 添加后按排序号排序
|
||||
|
||||
@@ -16,15 +16,15 @@
|
||||
v-model="form.cardNo"
|
||||
class="card-number-input"
|
||||
placeholder="单位自编,与网络直报一致"
|
||||
maxlength="20"
|
||||
:disabled="readOnly || dialogReadOnly"
|
||||
maxlength="12"
|
||||
:disabled="readOnly"
|
||||
/>
|
||||
</el-space>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<el-card class="report-form" shadow="never">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top" :disabled="readOnly || dialogReadOnly">
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-position="top" :disabled="readOnly">
|
||||
<!-- 患者姓名、家长姓名、身份证号 -->
|
||||
<el-row :gutter="16" class="form-row">
|
||||
<el-col :span="8" class="form-item">
|
||||
@@ -476,9 +476,9 @@
|
||||
<template #footer>
|
||||
<slot name="footer" :close="handleClose" :submit-loading="submitLoading">
|
||||
<el-space :size="16" justify="center" class="dialog-footer-space" style="display: flex; justify-content: center; width: 100%;">
|
||||
<el-button v-if="!(readOnly || dialogReadOnly)" type="primary" @click="handleSubmit" :loading="submitLoading" class="blue-button">保 存</el-button>
|
||||
<el-button v-if="!readOnly" type="primary" @click="handleSubmit" :loading="submitLoading" class="blue-button">保 存</el-button>
|
||||
<el-button type="info" @click="handleClose">关 闭</el-button>
|
||||
<el-button v-if="!(readOnly || dialogReadOnly)" type="danger" @click="handleReset">重 置</el-button>
|
||||
<el-button v-if="!readOnly" type="danger" @click="handleReset">重 置</el-button>
|
||||
</el-space>
|
||||
</slot>
|
||||
</template>
|
||||
@@ -510,7 +510,6 @@ const DISEASE_NAMES = {
|
||||
};
|
||||
|
||||
const dialogVisible = ref(false);
|
||||
const dialogReadOnly = ref(false);
|
||||
const formRef = ref(null);
|
||||
// 保存按钮加载状态,防止重复提交
|
||||
const submitLoading = ref(false);
|
||||
@@ -1038,9 +1037,8 @@ function resetAddressSelector() {
|
||||
* 以只读详情方式打开报卡弹窗,供报卡管理等页面复用医生站报卡样式。
|
||||
* @param {Object} reportData - 报卡详情数据
|
||||
*/
|
||||
function showReport(reportData = {}, readOnly = true) {
|
||||
function showReport(reportData = {}) {
|
||||
dialogVisible.value = true;
|
||||
dialogReadOnly.value = readOnly;
|
||||
|
||||
resetAddressSelector();
|
||||
initProvinceOptions();
|
||||
@@ -1071,7 +1069,7 @@ function showReport(reportData = {}, readOnly = true) {
|
||||
addressHouse: reportData.addressHouse || '',
|
||||
patientBelong: reportData.patientBelong || 1,
|
||||
occupation: reportData.occupation || '',
|
||||
caseClass: reportData.diseaseType != null ? String(reportData.diseaseType) : '',
|
||||
caseClass: reportData.caseClass != null ? String(reportData.caseClass) : '',
|
||||
onsetDate: normalizeDate(reportData.onsetDate),
|
||||
diagDate: normalizeDate(reportData.diagDate),
|
||||
deathDate: normalizeDate(reportData.deathDate),
|
||||
@@ -1080,13 +1078,13 @@ function showReport(reportData = {}, readOnly = true) {
|
||||
selectedClassB: diseaseSelection.selectedClassB,
|
||||
selectedClassC: diseaseSelection.selectedClassC,
|
||||
otherDisease: reportData.otherDisease || (diseaseCode === 'OTHER' ? reportData.diseaseName || '' : ''),
|
||||
diseaseType: reportData.diseaseSubtype || '',
|
||||
diseaseType: reportData.diseaseType || '',
|
||||
reportOrg: reportData.reportOrg || '',
|
||||
reportOrgPhone: reportData.reportOrgPhone || '',
|
||||
reportDoc: reportData.reportDoc || '',
|
||||
reportDate: normalizeDate(reportData.reportDate || reportData.createdAt),
|
||||
correctName: reportData.revisedDiseaseName || '',
|
||||
withdrawReason: reportData.returnReason || '',
|
||||
correctName: reportData.correctName || '',
|
||||
withdrawReason: reportData.withdrawReason || '',
|
||||
remark: reportData.remark || '',
|
||||
encounterId: reportData.encounterId || reportData.visitId || '',
|
||||
patientId: reportData.patientId || reportData.patId || '',
|
||||
@@ -1207,7 +1205,6 @@ function calculateAge() {
|
||||
*/
|
||||
async function show(diagnosisData) {
|
||||
dialogVisible.value = true;
|
||||
dialogReadOnly.value = false;
|
||||
|
||||
// 重置地址选择器状态
|
||||
resetAddressSelector();
|
||||
@@ -1241,13 +1238,14 @@ async function show(diagnosisData) {
|
||||
let cardNo = '';
|
||||
try {
|
||||
const res = await getNextCardNo(orgCode);
|
||||
if (res.code === 200 && res.data && res.data.length >= 12) {
|
||||
if (res.code === 200 && res.data) {
|
||||
cardNo = res.data;
|
||||
} else {
|
||||
cardNo = 'TEMP_' + Date.now();
|
||||
}
|
||||
// API失败或返回不合规时保持为空字符串,由用户手动填写或后端自动生成
|
||||
} catch (err) {
|
||||
console.error('获取卡片编号失败:', err);
|
||||
// 保持为空,不使用不合规的临时值
|
||||
cardNo = 'TEMP_' + Date.now();
|
||||
}
|
||||
|
||||
form.value = {
|
||||
@@ -1318,11 +1316,7 @@ async function show(diagnosisData) {
|
||||
// 系统关联信息
|
||||
encounterId: patientInfo.encounterId || '', // 就诊ID
|
||||
patientId: patientInfo.patientId || '', // 患者ID
|
||||
diagnosisId: (diagnosisData?.conditionId != null && diagnosisData?.conditionId !== '')
|
||||
? diagnosisData.conditionId
|
||||
: (diagnosisData?.definitionId != null && diagnosisData?.definitionId !== '')
|
||||
? diagnosisData.definitionId
|
||||
: '', // 诊断ID
|
||||
diagnosisId: diagnosisData?.conditionId || diagnosisData?.definitionId || '', // 诊断ID
|
||||
};
|
||||
|
||||
// 更新selectedDiseases数组
|
||||
@@ -1377,7 +1371,7 @@ async function buildSubmitData() {
|
||||
const submitData = {
|
||||
cardNo: formData.cardNo,
|
||||
visitId: props.patientInfo?.encounterId || formData.encounterId || null,
|
||||
diagId: formData.diagnosisId ? Number(formData.diagnosisId) : null,
|
||||
diagId: formData.diagnosisId || null,
|
||||
patId: formData.patientId || null,
|
||||
idType: 1, // 默认身份证
|
||||
idNo: formData.idNo,
|
||||
@@ -1430,9 +1424,9 @@ async function buildSubmitData() {
|
||||
function validateFormManually() {
|
||||
const errors = [];
|
||||
|
||||
// 卡片编号验证(至少12位,后端自动生成16位编号)
|
||||
if (form.value.cardNo && form.value.cardNo.length < 12) {
|
||||
errors.push('卡片编号至少12位');
|
||||
// 卡片编号验证(可选,但如果填写了必须是12位)
|
||||
if (form.value.cardNo && form.value.cardNo.length !== 12) {
|
||||
errors.push('卡片编号必须为12位');
|
||||
}
|
||||
|
||||
// 身份证号验证
|
||||
@@ -1543,12 +1537,6 @@ async function handleSubmit() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查诊断ID是否有效(后端 @NotNull 校验要求)
|
||||
if (!form.value.diagnosisId) {
|
||||
proxy.$modal.msgError('诊断信息不完整,请重新选择诊断后重试');
|
||||
return;
|
||||
}
|
||||
|
||||
// 开始加载状态,防止重复提交
|
||||
submitLoading.value = true;
|
||||
|
||||
|
||||
@@ -316,7 +316,6 @@
|
||||
<span class="cat-title">{{ cat.categoryName }}</span>
|
||||
<span v-if="categoryLoadingSet.has(cat.typeId)" class="loading-dot"></span>
|
||||
</template>
|
||||
<!-- 检查项目(部位/项目列表) -->
|
||||
<div
|
||||
v-for="item in cat.items"
|
||||
:key="item.id"
|
||||
@@ -334,27 +333,6 @@
|
||||
<div v-if="categoryLoadingSet.has(cat.typeId)" class="category-loading-hint">
|
||||
加载中...
|
||||
</div>
|
||||
<!-- Bug #428修复: 渲染分类联动加载的检查方法列表 -->
|
||||
<div
|
||||
v-if="cat.methods && cat.methods.length > 0"
|
||||
class="method-section"
|
||||
>
|
||||
<div class="method-section-title">检查方法</div>
|
||||
<div
|
||||
v-for="method in cat.methods"
|
||||
:key="method.id"
|
||||
class="method-row"
|
||||
>
|
||||
<el-checkbox
|
||||
:model-value="isMethodSelected(method, cat)"
|
||||
@change="(val) => handleMethodSelect(val, method, cat)"
|
||||
class="method-checkbox"
|
||||
>
|
||||
{{ method.name }}
|
||||
</el-checkbox>
|
||||
<span class="method-price-tag">¥{{ method.packagePrice || method.price || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
@@ -682,7 +660,6 @@ async function handleCategoryExpand(cat) {
|
||||
code: m.code,
|
||||
price: m.price || 0,
|
||||
packageName: m.packageName || '',
|
||||
packageId: m.packageId || null,
|
||||
packagePrice: m.packagePrice || null,
|
||||
serviceFee: m.serviceFee || null
|
||||
}));
|
||||
@@ -1026,18 +1003,12 @@ function handleRowClick(row) {
|
||||
code: md.code,
|
||||
price: m.itemFee || 0, // fallback 到已保存的价格
|
||||
packageName: md.packageName || '',
|
||||
packageId: md.packageId || null,
|
||||
packagePrice: md.packagePrice || null, // Bug #384修复: 套餐价格
|
||||
serviceFee: md.serviceFee || null
|
||||
}));
|
||||
// 如果有已保存的检查方法信息,尝试匹配
|
||||
if (m.checkMethodId) {
|
||||
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) {
|
||||
@@ -1076,92 +1047,6 @@ function handleDelete(row) {
|
||||
});
|
||||
}
|
||||
|
||||
// Bug #428修复: 判断某个检查方法是否已被选中(任意项目关联了该方法)
|
||||
function isMethodSelected(method, cat) {
|
||||
return selectedItems.value.some(item =>
|
||||
item.selectedMethod?.id === method.id && item.checkType === cat.typeName
|
||||
);
|
||||
}
|
||||
|
||||
// Bug #428修复: 勾选检查方法
|
||||
async function handleMethodSelect(checked, method, cat) {
|
||||
if (checked) {
|
||||
// 找到该方法所属的第一个检查项目
|
||||
const targetItem = cat.items[0];
|
||||
if (!targetItem) {
|
||||
// 如果分类下没有项目,尝试从其他分类找同名项目或创建
|
||||
console.warn('分类下没有检查项目,无法关联方法');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果该项目已存在,只更新 selectedMethod
|
||||
const existingItem = selectedItems.value.find(s => s.id === targetItem.id);
|
||||
if (existingItem) {
|
||||
existingItem.selectedMethod = method;
|
||||
// 从方法中获取套餐信息
|
||||
if (method.packageId) {
|
||||
existingItem.isPackage = true;
|
||||
existingItem.packageId = method.packageId;
|
||||
// 预加载套餐明细
|
||||
loadPackageDetailsForItem(existingItem);
|
||||
}
|
||||
updateMethodDisplay();
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果该项目不存在,创建一个并关联方法
|
||||
if (selectedItems.value.length > 0) {
|
||||
const currentCategory = selectedItems.value[0].checkType;
|
||||
const newCategory = cat.typeCode || '';
|
||||
if (currentCategory !== newCategory) {
|
||||
ElMessage.warning('一个检查单不能同时选择多个项目类型的检查项目');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const newItem = {
|
||||
id: targetItem.id, name: targetItem.name,
|
||||
price: targetItem.price, quantity: 1,
|
||||
serviceFee: targetItem.serviceFee || 0,
|
||||
unit: targetItem.unit || '次',
|
||||
applyPart: targetItem.name,
|
||||
checkType: cat.typeName,
|
||||
nationalCode: targetItem.nationalCode || '',
|
||||
checked: true,
|
||||
methods: [method],
|
||||
selectedMethod: method,
|
||||
expanded: false,
|
||||
// 从方法中获取套餐信息(优先级高于项目本身的 packageName)
|
||||
isPackage: !!method.packageId || !!targetItem.packageName,
|
||||
packageId: method.packageId || targetItem.packageId || null
|
||||
};
|
||||
selectedItems.value.push(newItem);
|
||||
|
||||
// 如果是套餐,预加载套餐明细
|
||||
if (newItem.isPackage && newItem.packageId) {
|
||||
loadPackageDetailsForItem(newItem);
|
||||
}
|
||||
|
||||
// 自动回填执行科室
|
||||
if (selectedItems.value.length === 1 && cat?.performDeptName) {
|
||||
form.performDeptCode = cat.performDeptName;
|
||||
}
|
||||
|
||||
// 同时勾选左侧项目的 checkbox
|
||||
targetItem.checked = true;
|
||||
|
||||
} else {
|
||||
// 取消选择方法:将 selectedItems 中关联该方法的项的 selectedMethod 清空
|
||||
const itemsWithMethod = selectedItems.value.filter(
|
||||
item => item.selectedMethod?.id === method.id
|
||||
);
|
||||
for (const item of itemsWithMethod) {
|
||||
item.selectedMethod = null;
|
||||
}
|
||||
}
|
||||
updateMethodDisplay();
|
||||
}
|
||||
|
||||
// ====== 勾选逻辑 ======
|
||||
async function handleItemSelect(checked, item, cat) {
|
||||
if (checked) {
|
||||
@@ -1185,7 +1070,6 @@ async function handleItemSelect(checked, item, cat) {
|
||||
code: m.code,
|
||||
price: m.price || item.price, // fallback 到项目价格
|
||||
packageName: m.packageName || '',
|
||||
packageId: m.packageId || null,
|
||||
packagePrice: m.packagePrice || null, // Bug #384修复: 套餐价格
|
||||
serviceFee: m.serviceFee || null // Bug #384修复: 服务费
|
||||
}));
|
||||
@@ -1483,53 +1367,6 @@ defineExpose({ getList });
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
/* Bug #428修复: 分类下检查方法区域样式 */
|
||||
.method-section {
|
||||
padding: 6px 8px;
|
||||
background: #f0f7ff;
|
||||
border-radius: 4px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.method-section-title {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #409eff;
|
||||
margin-bottom: 4px;
|
||||
padding-bottom: 3px;
|
||||
border-bottom: 1px dashed #d9ecff;
|
||||
}
|
||||
|
||||
.method-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 3px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.method-row:hover {
|
||||
background: #e8f4ff;
|
||||
}
|
||||
|
||||
.method-checkbox {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.method-checkbox :deep(.el-checkbox__label) {
|
||||
font-size: 12px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.method-price-tag {
|
||||
font-size: 11px;
|
||||
color: #e6a23c;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
/* 已选择 tags */
|
||||
.selected-panel {
|
||||
width: 140px; /* Bug #384修复: 加宽以适应展开内容 */
|
||||
@@ -1601,41 +1438,6 @@ defineExpose({ getList });
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
/* Bug #428修复: 套餐明细列表样式 */
|
||||
.package-details-list {
|
||||
padding: 6px 10px;
|
||||
background: #fffbe6;
|
||||
border-top: 1px solid #ffe58f;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.detail-row:hover {
|
||||
background: #fff9e6;
|
||||
}
|
||||
|
||||
.detail-name {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.detail-info {
|
||||
color: #909399;
|
||||
font-size: 10px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Bug #384修复: 检查方法勾选框列表 */
|
||||
.method-list {
|
||||
padding: 6px 10px;
|
||||
|
||||
@@ -1013,29 +1013,15 @@ const mapAdviceTypeLabel = (type, adviceTableName) => {
|
||||
if (type === 2 && adviceTableName === 'adm_device_definition') {
|
||||
return '耗材';
|
||||
}
|
||||
|
||||
|
||||
// 🔧 Bug Fix: 处理检查类型(adviceType=23)
|
||||
// 检查类型属于诊疗类,应该显示为"检查"
|
||||
if (type === 23) {
|
||||
return '检查';
|
||||
}
|
||||
|
||||
|
||||
const found = adviceTypeList.value.find((item) => item.value === type);
|
||||
if (found) {
|
||||
return found.label;
|
||||
}
|
||||
|
||||
// 🔧 Bug #458 Fix: 诊疗/手术类型字典缺失时的兜底,避免保存后"医嘱类型"列显示为空
|
||||
if (adviceTableName === 'wor_activity_definition' || adviceTableName === 'wor_service_request') {
|
||||
if (type === 6) return '手术';
|
||||
if (type === 4) return '手术';
|
||||
if (type === 1) return '检验';
|
||||
if (type === 2) return '检查';
|
||||
if (type === 5) return '其他';
|
||||
return '诊疗';
|
||||
}
|
||||
|
||||
return '';
|
||||
return found ? found.label : '';
|
||||
};
|
||||
|
||||
// 西药处方管理相关变量
|
||||
@@ -2509,13 +2495,11 @@ function handleSave(prescriptionId) {
|
||||
|
||||
// 🔧 BugFix#318: 从 parsedContent 提取标准医嘱字段,排除手术特有字段
|
||||
const standardFields = [
|
||||
'accountId', 'chargeItemId', 'conditionDefinitionId', 'conditionId',
|
||||
'contentJson', 'definitionDetailId', 'definitionId', 'diagnosisName',
|
||||
'dosageInstruction', 'effectiveOrgId', 'encounterDiagnosisId',
|
||||
'encounterId', 'lotNumber', 'patientId', 'practitionerId',
|
||||
'prescriptionNo', 'skinTestFlag', 'unitPrice', 'volume', 'ybClassEnum',
|
||||
// 🔧 Bug Fix: 添加 therapyEnum 字段(医嘱类型:1=长期, 2=临时)
|
||||
'therapyEnum'
|
||||
'accountId', 'chargeItemId', 'conditionDefinitionId', 'conditionId',
|
||||
'contentJson', 'definitionDetailId', 'definitionId', 'diagnosisName',
|
||||
'dosageInstruction', 'effectiveOrgId', 'encounterDiagnosisId',
|
||||
'encounterId', 'lotNumber', 'patientId', 'practitionerId',
|
||||
'prescriptionNo', 'skinTestFlag', 'unitPrice', 'volume', 'ybClassEnum'
|
||||
];
|
||||
let filteredContent = {};
|
||||
standardFields.forEach(field => {
|
||||
@@ -3159,9 +3143,7 @@ function handleSaveBatch(prescriptionId) {
|
||||
// 🔧 Bug Fix: 添加 definitionId 和 definitionDetailId 字段
|
||||
'definitionId', 'definitionDetailId',
|
||||
// 🔧 Bug Fix: 添加 categoryEnum 字段(耗材必填)
|
||||
'categoryEnum',
|
||||
// 🔧 Bug Fix: 添加 therapyEnum 字段(医嘱类型:1=长期, 2=临时)
|
||||
'therapyEnum'
|
||||
'categoryEnum'
|
||||
];
|
||||
let filteredItem = {};
|
||||
standardItemFields.forEach(field => {
|
||||
@@ -3360,7 +3342,7 @@ function syncGroupFields(row) {
|
||||
}
|
||||
}
|
||||
|
||||
async function setValue(row) {
|
||||
function setValue(row) {
|
||||
unitCodeList.value = [];
|
||||
unitCodeList.value.push({ value: row.unitCode, label: row.unitCode_dictText, type: 'unit' });
|
||||
|
||||
@@ -3412,8 +3394,8 @@ async function setValue(row) {
|
||||
showPopover: false, // 确保查询框关闭
|
||||
};
|
||||
console.log('[BugFix] setValue - prescriptionList[rowIndex].adviceType_dictText:', prescriptionList.value[rowIndex.value].adviceType_dictText);
|
||||
// 🔧 Bug #455: 执行科室默认逻辑:使用positionId(诊疗执行科室配置) → 患者就诊科室,不再使用row.orgId(项目所属科室)
|
||||
prescriptionList.value[rowIndex.value].orgId = row.positionId || props.patientInfo?.orgId;
|
||||
// 🔧 修复执行科室逻辑:优先使用项目维护的所属科室(row.orgId),其次使用positionId,最后回退到患者科室
|
||||
prescriptionList.value[rowIndex.value].orgId = row.orgId || row.positionId || props.patientInfo?.orgId;
|
||||
prescriptionList.value[rowIndex.value].dose = row.dose || row.doseQuantity;
|
||||
prescriptionList.value[rowIndex.value].quantity = row.quantity || 1;
|
||||
prescriptionList.value[rowIndex.value].unitCodeList = unitCodeList.value;
|
||||
@@ -3532,7 +3514,7 @@ async function setValue(row) {
|
||||
prescriptionList.value[rowIndex.value].positionId = finalLocationId;
|
||||
}
|
||||
} else {
|
||||
await getOrgList();
|
||||
getOrgList();
|
||||
// 会诊类型(adviceType == 5)和诊疗类型(adviceType == 3)的处理
|
||||
if (row.adviceType == 5) {
|
||||
// 会诊类型:设置默认值
|
||||
|
||||
@@ -1133,13 +1133,12 @@ function submitForm() {
|
||||
// 新增手术
|
||||
addSurgery(form.value).then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$modal.msgSuccess(res.msg || '手术申请提交成功!')
|
||||
proxy.$modal.msgSuccess(res.msg || '新增成功')
|
||||
// 保存麻醉方式
|
||||
sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum)
|
||||
open.value = false
|
||||
emit('saved') // 通知父组件刷新医嘱列表
|
||||
// 刷新手术申请列表
|
||||
getList()
|
||||
emit('saved') // 🔧 触发保存事件,通知父组件刷新医嘱列表
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg || '新增手术失败,请检查表单信息')
|
||||
}
|
||||
@@ -1151,13 +1150,12 @@ function submitForm() {
|
||||
// 修改手术
|
||||
updateSurgery(form.value).then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$modal.msgSuccess(res.msg || '手术申请修改成功!')
|
||||
proxy.$modal.msgSuccess(res.msg || '修改成功')
|
||||
// 保存麻醉方式
|
||||
sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum)
|
||||
open.value = false
|
||||
emit('saved') // 通知父组件刷新医嘱列表
|
||||
// 刷新手术申请列表
|
||||
getList()
|
||||
emit('saved') // 🔧 触发保存事件,通知父组件刷新医嘱列表
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg || '更新手术失败,请检查表单信息')
|
||||
}
|
||||
|
||||
@@ -151,12 +151,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<InfectiousDiseaseReportDialog
|
||||
ref="infectiousDiseaseReportRef"
|
||||
:read-only="detailMode === 'view'"
|
||||
@success="detailVisible = false"
|
||||
@close="detailVisible = false"
|
||||
/>
|
||||
<el-dialog
|
||||
v-model="detailVisible"
|
||||
:title="detailMode === 'view' ? '报卡详情 - 中华人民共和国传染病报告卡' : '编辑报卡 - 中华人民共和国传染病报告卡'"
|
||||
width="1100px"
|
||||
destroy-on-close
|
||||
class="card-detail-dialog"
|
||||
>
|
||||
<InfectiousReport
|
||||
:mode=" detailMode"
|
||||
:card-data="currentCard"
|
||||
@submit-edit="handleSaveEdit"
|
||||
style="max-height: 75vh; overflow-y: auto;"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -164,7 +175,7 @@
|
||||
import { ref, reactive, onMounted, onActivated, onBeforeUnmount, nextTick, computed } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { DataAnalysis, Warning, CircleCheck, Check, RefreshRight } from '@element-plus/icons-vue';
|
||||
import InfectiousDiseaseReportDialog from '../components/diagnosis/infectiousDiseaseReportDialog.vue';
|
||||
import InfectiousReport from '../components/infectiousReport/index.vue';
|
||||
import {
|
||||
getDoctorCardStatistics,
|
||||
getDoctorCardList,
|
||||
@@ -174,6 +185,7 @@ import {
|
||||
batchDeleteCards,
|
||||
exportCardToWord,
|
||||
getCardDetail,
|
||||
updateDoctorCard,
|
||||
} from './api';
|
||||
|
||||
const loading = ref(false);
|
||||
@@ -199,7 +211,7 @@ const queryParams = reactive({
|
||||
|
||||
const detailVisible = ref(false);
|
||||
const detailMode = ref('view');
|
||||
const infectiousDiseaseReportRef = ref(null);
|
||||
const currentCard = ref({});
|
||||
|
||||
// 计算表格高度:根据视口高度动态调整
|
||||
const tableHeight = computed(() => {
|
||||
@@ -315,11 +327,9 @@ async function handleView(row) {
|
||||
try {
|
||||
const res = await getCardDetail(row.cardNo);
|
||||
if (res.code === 200) {
|
||||
currentCard.value = res.data || {};
|
||||
detailMode.value = 'view';
|
||||
detailVisible.value = true;
|
||||
nextTick(() => {
|
||||
infectiousDiseaseReportRef.value?.showReport(res.data || {});
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取详情失败');
|
||||
@@ -330,17 +340,57 @@ async function handleEdit(row) {
|
||||
try {
|
||||
const res = await getCardDetail(row.cardNo);
|
||||
if (res.code === 200) {
|
||||
currentCard.value = res.data || {};
|
||||
detailMode.value = 'edit';
|
||||
detailVisible.value = true;
|
||||
nextTick(() => {
|
||||
infectiousDiseaseReportRef.value?.showReport(res.data || {}, false);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('获取详情失败');
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSaveEdit(submitData) {
|
||||
// submitData 来自 InfectiousReport 组件的 submit-edit 事件
|
||||
try {
|
||||
const updateData = {
|
||||
cardNo: submitData.cardNo,
|
||||
phone: submitData.phone,
|
||||
contactPhone: submitData.contactPhone,
|
||||
onsetDate: submitData.onsetDate,
|
||||
diagDate: submitData.diagDate,
|
||||
diseaseCode: submitData.diseaseCode,
|
||||
diseaseType: submitData.diseaseType,
|
||||
otherDisease: submitData.otherDisease,
|
||||
caseClass: submitData.caseClass,
|
||||
occupation: submitData.occupation,
|
||||
patientBelong: submitData.patientBelong,
|
||||
addressProv: submitData.addressProv,
|
||||
addressCity: submitData.addressCity,
|
||||
addressCounty: submitData.addressCounty,
|
||||
addressTown: submitData.addressTown,
|
||||
addressVillage: submitData.addressVillage,
|
||||
addressHouse: submitData.addressHouse,
|
||||
workplace: submitData.workplace,
|
||||
parentName: submitData.parentName,
|
||||
deathDate: submitData.deathDate,
|
||||
correctName: submitData.correctName,
|
||||
withdrawReason: submitData.withdrawReason,
|
||||
remark: submitData.remark,
|
||||
};
|
||||
|
||||
const res = await updateDoctorCard(updateData);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('保存成功');
|
||||
detailVisible.value = false;
|
||||
getList();
|
||||
} else {
|
||||
ElMessage.error(res.msg || '保存失败');
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('保存失败:' + (error.message || '网络错误'));
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit(row) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认提交该报卡?', '提示', {
|
||||
@@ -750,4 +800,17 @@ function handleResize() {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 报卡详情弹窗 */
|
||||
:deep(.card-detail-dialog .el-dialog__body) {
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.card-detail-dialog .infectious-report-container) {
|
||||
padding: 16px;
|
||||
height: auto;
|
||||
max-height: 70vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -79,7 +79,7 @@
|
||||
<el-table-column prop="patientName" label="患者姓名" width="120" />
|
||||
<el-table-column prop="name" label="申请单名称" width="140" />
|
||||
<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 label="申请单状态" width="120" align="center">
|
||||
<template #default="scope">
|
||||
@@ -118,7 +118,7 @@
|
||||
<el-descriptions-item label="创建时间">{{
|
||||
currentDetail.createTime || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请单号">{{
|
||||
<el-descriptions-item label="处方号">{{
|
||||
currentDetail.prescriptionNo || '-'
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请者">{{
|
||||
@@ -168,7 +168,7 @@ import {computed, getCurrentInstance, ref, watch} from 'vue';
|
||||
import {Refresh, Search} from '@element-plus/icons-vue';
|
||||
import {patientInfo} from '../../store/patient.js';
|
||||
import {getCheck} from './api';
|
||||
import {getDepartmentList} from '@/api/public.js';
|
||||
import {getOrgList} from '@/views/doctorstation/components/api.js';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
@@ -293,8 +293,8 @@ const hasMatchedFields = computed(() => {
|
||||
|
||||
/** 查询科室 */
|
||||
const getLocationInfo = () => {
|
||||
getDepartmentList().then((res) => {
|
||||
orgOptions.value = res.data || [];
|
||||
getOrgList().then((res) => {
|
||||
orgOptions.value = res.data.records;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -306,19 +306,17 @@ const recursionFun = (targetDepartment) => {
|
||||
name = obj.name;
|
||||
}
|
||||
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;
|
||||
}
|
||||
for (let index = 0; index < subObjArray.length; index++) {
|
||||
const item = subObjArray[index];
|
||||
if (item.id == targetDepartment) {
|
||||
name = item.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return name;
|
||||
};
|
||||
|
||||
const handleViewDetail = async (row) => {
|
||||
const handleViewDetail = (row) => {
|
||||
console.log('targetDepartment========>', JSON.stringify(row));
|
||||
|
||||
currentDetail.value = row;
|
||||
@@ -326,15 +324,6 @@ const handleViewDetail = async (row) => {
|
||||
if (row.descJson) {
|
||||
try {
|
||||
const obj = JSON.parse(row.descJson);
|
||||
// 确保科室数据已加载
|
||||
if (!orgOptions.value || orgOptions.value.length === 0) {
|
||||
await new Promise((resolve) => {
|
||||
getDepartmentList().then((res) => {
|
||||
orgOptions.value = res.data || [];
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
obj.targetDepartment = recursionFun(obj.targetDepartment);
|
||||
descJsonData.value = obj;
|
||||
} catch (e) {
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="待签发" value="0" />
|
||||
<el-option label="已签发" value="1" />
|
||||
<el-option label="已采集" value="2" />
|
||||
<el-option label="已收样" value="3" />
|
||||
<el-option label="报告已出" value="4" />
|
||||
<el-option label="已作废" value="5" />
|
||||
</el-select>
|
||||
@@ -296,6 +298,8 @@ const parseBillStatus = (status) => {
|
||||
const statusMap = {
|
||||
'0': '待签发',
|
||||
'1': '已签发',
|
||||
'2': '已采集',
|
||||
'3': '已收样',
|
||||
'4': '报告已出',
|
||||
'5': '已作废',
|
||||
};
|
||||
|
||||
@@ -164,7 +164,7 @@ onMounted(() => {
|
||||
* type(1:watch监听类型 2:点击保存类型)
|
||||
* selectProjectIds(选中项目的id数组)
|
||||
* */
|
||||
const projectWithDepartment = (selectProjectIds, type) => {
|
||||
const projectWithDepartment = (selectProjectIds) => {
|
||||
//1.获取选中的项目 2.判断项目的执行科室是否相同 3.判断执行科室是否配置 4.将项目的执行科室复值到执行科室下拉选位置
|
||||
let isRelease = true;
|
||||
// 选中项目的数组
|
||||
|
||||
@@ -483,7 +483,7 @@ const submit = () => {
|
||||
encounterId: patientInfo.value.encounterId,
|
||||
organizationId: patientInfo.value.inHospitalOrgId,
|
||||
requestFormId: '',
|
||||
name: applicationListAllFilter.map(item => item.adviceName).join('、'),
|
||||
name: '检查申请单',
|
||||
descJson: JSON.stringify(submitForm),
|
||||
categoryEnum: '2',
|
||||
}).then((res) => {
|
||||
|
||||
@@ -6,15 +6,13 @@
|
||||
<template>
|
||||
<div class="surgery-container">
|
||||
<div class="transfer-wrapper">
|
||||
<div v-loading="loading" style="min-height: 300px;">
|
||||
<el-transfer
|
||||
v-model="transferValue"
|
||||
:data="applicationList"
|
||||
filter-placeholder="项目代码/名称"
|
||||
filterable
|
||||
:titles="['未选择', '已选择']"
|
||||
/>
|
||||
</div>
|
||||
<el-transfer
|
||||
v-model="transferValue"
|
||||
:data="applicationList"
|
||||
filter-placeholder="项目代码/名称"
|
||||
filterable
|
||||
:titles="['未选择', '已选择']"
|
||||
/>
|
||||
</div>
|
||||
<div class="bloodTransfusion-form">
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="120px" class="demo-ruleForm">
|
||||
@@ -106,13 +104,11 @@ const state = reactive({});
|
||||
const applicationListAll = ref([]);
|
||||
const applicationList = ref([]);
|
||||
const orgOptions = ref([]); // 科室选项
|
||||
const loading = ref(false); // 加载状态
|
||||
const getList = () => {
|
||||
if (!patientInfo.value?.inHospitalOrgId) {
|
||||
applicationList.value = [];
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
getApplicationList({
|
||||
pageSize: 500,
|
||||
pageNum: 1,
|
||||
@@ -142,9 +138,6 @@ const getList = () => {
|
||||
.catch((e) => {
|
||||
console.warn('手术项目列表加载失败(可能无权限):', e?.message || e);
|
||||
applicationList.value = [];
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
const transferValue = ref([]);
|
||||
@@ -308,7 +301,7 @@ function getDiagnosisList() {
|
||||
}
|
||||
});
|
||||
}
|
||||
defineExpose({ state, submit, getLocationInfo, getDiagnosisList, getList });
|
||||
defineExpose({ state, submit, getLocationInfo, getDiagnosisList });
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.surgery-container {
|
||||
|
||||
@@ -801,7 +801,9 @@ function clickRowDb(row, column, event) {
|
||||
return;
|
||||
}
|
||||
row.showPopover = false;
|
||||
// 仅”待签发(statusEnum==1)”允许编辑;”已签发(statusEnum==2)”及之后状态不允许编辑
|
||||
// 允许所有 statusEnum==1 的医嘱进入编辑:
|
||||
// 1. 新医嘱(无 requestId):待保存
|
||||
// 2. 护士退回医嘱(有 requestId):退回后状态重置为 DRAFT(1),需允许医生编辑修改后重新签发
|
||||
if (row.statusEnum == 1) {
|
||||
// 确保治疗类型为字符串,方便与单选框 label 对齐,默认为长期医嘱('1')
|
||||
row.therapyEnum = String(row.therapyEnum ?? '1');
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
>
|
||||
<div>
|
||||
<el-radio-group v-model="type" class="ml20" @change="handleRadioChange">
|
||||
<el-radio :label="null">全部</el-radio>
|
||||
<el-radio :label="1">长期</el-radio>
|
||||
<el-radio :label="2">临时</el-radio>
|
||||
<el-radio :label="1">全部</el-radio>
|
||||
<el-radio :label="2">长期</el-radio>
|
||||
<el-radio :label="3">临时</el-radio>
|
||||
</el-radio-group>
|
||||
<el-button class="ml20" type="primary" plain @click="handleGetPrescription">
|
||||
查询
|
||||
@@ -159,7 +159,7 @@ import {formatDateStr} from '@/utils/index';
|
||||
const activeNames = ref([]);
|
||||
const prescriptionList = ref([]);
|
||||
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
|
||||
const type = ref(null);
|
||||
const type = ref(1);
|
||||
const { proxy } = getCurrentInstance();
|
||||
const loading = ref(false);
|
||||
const chooseAll = ref(false);
|
||||
@@ -181,7 +181,7 @@ function handleGetPrescription() {
|
||||
getPrescriptionList({
|
||||
encounterIds: encounterIds,
|
||||
requestStatus: props.requestStatus,
|
||||
...(type.value != null ? { therapyEnum: type.value } : {}),
|
||||
...(type.value !== undefined ? { therapyEnum: type.value } : {}),
|
||||
pageSize: 10000,
|
||||
pageNo: 1,
|
||||
}).then((res) => {
|
||||
|
||||
@@ -744,7 +744,11 @@ function handleSubmitApproval() {
|
||||
} else {
|
||||
submitApproval(receiptHeaderForm.busNo).then((response) => {
|
||||
proxy.$modal.msgSuccess('提交审批成功');
|
||||
// proxy.$tab.closePage(route).then(({ visitedViews }) => { // 关闭当前页
|
||||
// toLastView(visitedViews, route)
|
||||
// })
|
||||
tagsViewStore.delView(router.currentRoute.value);
|
||||
// 跳转到调拨管理页面
|
||||
router.replace({ path: 'transferManagentList' });
|
||||
});
|
||||
}
|
||||
@@ -867,6 +871,7 @@ function handleUnitCodeChange(row, index, value) {
|
||||
}
|
||||
|
||||
function handleItemQuantityChange(row, value) {
|
||||
debugger;
|
||||
let quantityTemp = ''; // 转换成小单位的临时变量 做校验
|
||||
// 大单位情况
|
||||
if (row.unitCodeMap[row.unitCode] == 'unit') {
|
||||
@@ -877,6 +882,12 @@ function handleItemQuantityChange(row, value) {
|
||||
row.itemQuantity = value;
|
||||
quantityTemp = value;
|
||||
}
|
||||
if (row.totalSourceQuantity < quantityTemp) {
|
||||
proxy.$modal.msgWarning('调拨数量不可超出源库存数量');
|
||||
row.itemQuantity = 0;
|
||||
row.itemQuantityDisplay = 0;
|
||||
return;
|
||||
}
|
||||
row.totalPrice = ((row.price * quantityTemp) / row.partPercent).toFixed(2);
|
||||
// 更新总数据中对应的记录
|
||||
const totalIndex = totalIncentoryInfoList.value.findIndex((item) => item.id === row.id);
|
||||
@@ -907,12 +918,11 @@ function remakeBlur(row, index) {
|
||||
editBatchTransfer(index);
|
||||
}
|
||||
function handleSave() {
|
||||
// 校验单价
|
||||
const invalidPriceRow = totalIncentoryInfoList.value.find(
|
||||
const invalidRow = totalIncentoryInfoList.value.find(
|
||||
(row) => !row.price || row.price <= 0
|
||||
);
|
||||
if (invalidPriceRow) {
|
||||
proxy.$modal.msgError('调拨单价不能为空或为0,请检查!');
|
||||
if (invalidRow) {
|
||||
proxy.$message.warning('调拨单价不能为空或为0,请检查!');
|
||||
return;
|
||||
}
|
||||
addTransferProductBatch(totalIncentoryInfoList.value).then((res) => {
|
||||
|
||||
@@ -970,6 +970,12 @@ function handleItemQuantityChange(row, value) {
|
||||
row.itemQuantity = value;
|
||||
quantityTemp = value;
|
||||
}
|
||||
if (row.totalSourceQuantity < quantityTemp) {
|
||||
proxy.$modal.msgWarning('调拨数量不可超出源库存数量');
|
||||
row.itemQuantity = 0;
|
||||
row.itemQuantityDisplay = 0;
|
||||
return;
|
||||
}
|
||||
row.totalPrice = ((row.price * quantityTemp) / row.partPercent).toFixed(2);
|
||||
}
|
||||
|
||||
@@ -1016,7 +1022,11 @@ function handleSubmitApproval() {
|
||||
} else {
|
||||
submitApproval(receiptHeaderForm.busNo).then((response) => {
|
||||
proxy.$modal.msgSuccess('提交审批成功');
|
||||
// proxy.$tab.closePage(route).then(({ visitedViews }) => { // 关闭当前页
|
||||
// toLastView(visitedViews, route)
|
||||
// })
|
||||
tagsViewStore.delView(router.currentRoute.value);
|
||||
// 跳转到调拨管理页面
|
||||
router.replace({ path: 'transferManagentList' });
|
||||
store.clearCurrentDataDB();
|
||||
});
|
||||
|
||||
@@ -1416,12 +1416,9 @@ function closeChargeDialog() {
|
||||
if (prescriptionRef.value && prescriptionRef.value.closeAllPopovers) {
|
||||
prescriptionRef.value.closeAllPopovers()
|
||||
}
|
||||
// 等 Vue 完成 DOM 更新后再关闭弹窗,确保 popover 先消失
|
||||
nextTick(() => {
|
||||
showChargeDialog.value = false
|
||||
chargePatientInfo.value = {}
|
||||
chargeSurgeryInfo.value = {}
|
||||
})
|
||||
showChargeDialog.value = false
|
||||
chargePatientInfo.value = {}
|
||||
chargeSurgeryInfo.value = {}
|
||||
}
|
||||
|
||||
// 🔧 新增:标志位,用于区分是"打开"还是"刷新"
|
||||
|
||||
Reference in New Issue
Block a user