Compare commits
44 Commits
cceaf7fb07
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16f6fbb8cf | ||
| 28f85ceb05 | |||
|
|
b43688e483 | ||
|
|
0bf29a53a4 | ||
|
|
0c70b224f9 | ||
|
|
449209a79b | ||
|
|
d6663c9667 | ||
|
|
53d29cbe14 | ||
|
|
e16a70dd50 | ||
|
|
bba63d2f1b | ||
|
|
f3d011951b | ||
| 7dc76d7b59 | |||
| b2dec2667a | |||
|
|
879d31b51d | ||
|
|
473a5f7f06 | ||
| 2eec988c56 | |||
| 8820048d55 | |||
| 6af7720470 | |||
|
|
5f134945ab | ||
| bc12cc1b08 | |||
| 17b8ea7192 | |||
|
|
2bfdd686c7 | ||
|
|
066cfaba46 | ||
| e8850e85fc | |||
| d083a3123a | |||
| 96c1927f8d | |||
| bdac9d0709 | |||
| 8faba1ea21 | |||
| dd9b77f6bb | |||
| d45955f6de | |||
| f905915f34 | |||
|
|
52951d7296 | ||
| 3c47979913 | |||
| 9aad809322 | |||
| b7850e5b8a | |||
|
|
effcdfbbe6 | ||
| 4277a369d2 | |||
| cf3f971741 | |||
| 75737cf95c | |||
| 4b544dc214 | |||
| 597e621b69 | |||
| 725ac4b76a | |||
| 8e8b35faa4 | |||
| 664ee0312c |
@@ -59,8 +59,10 @@ public class CheckMethodAppServiceImpl implements ICheckMethodAppService {
|
||||
return R.fail("检查方法的检查类型不能为空!");
|
||||
}
|
||||
//2.保存
|
||||
boolean save = checkMethodService.save(checkMethod);
|
||||
return R.ok(save);
|
||||
checkMethodService.save(checkMethod);
|
||||
java.util.Map<String, Object> result = new java.util.HashMap<>();
|
||||
result.put("id", checkMethod.getId());
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,6 +48,16 @@ public class CheckTypeController extends BaseController {
|
||||
private final ICheckPackageDetailService checkPackageDetailService;
|
||||
private final ICheckPackageAppService checkPackageAppService;
|
||||
|
||||
/**
|
||||
* 获取所有检查类型列表(不分页,用于下拉选项)
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public AjaxResult getAllCheckTypes() {
|
||||
List<CheckType> list = checkTypeService.list(
|
||||
new QueryWrapper<CheckType>().orderByAsc("id"));
|
||||
return AjaxResult.success(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取检查类型列表(支持分页)
|
||||
*/
|
||||
|
||||
@@ -464,17 +464,86 @@ public class CommonServiceImpl implements ICommonService {
|
||||
*/
|
||||
@Override
|
||||
public List<LocationDto> getPractitionerWard() {
|
||||
// 查询当前登录者管理的病区
|
||||
// 获取当前登录用户信息
|
||||
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
||||
Long currentOrgId = SecurityUtils.getLoginUser().getOrgId();
|
||||
|
||||
log.info("getPractitionerWard - practitionerId: {}, currentOrgId: {}", practitionerId, currentOrgId);
|
||||
|
||||
// 获取用户配置的位置 ID 列表(可能包含科室、病区等)
|
||||
List<Long> locationIds = practitionerRoleService.getLocationIdsByPractitionerId(practitionerId);
|
||||
List<Location> locationList
|
||||
= locationService.getLocationList(locationIds, Collections.singletonList(LocationStatus.ACTIVE.getValue()));
|
||||
// 获取用户配置的科室 ID 列表
|
||||
List<Long> orgIds = practitionerRoleService.getOrgIdsByPractitionerId(practitionerId);
|
||||
|
||||
log.info("getPractitionerWard - locationIds: {}, orgIds: {}", locationIds, orgIds);
|
||||
|
||||
List<Location> wardList = new ArrayList<>();
|
||||
for (Location ward : locationList) {
|
||||
if (LocationForm.WARD.getValue().equals(ward.getFormEnum())) {
|
||||
wardList.add(ward);
|
||||
|
||||
// 方式 1:从 locationIds 中过滤出病区
|
||||
if (locationIds != null && !locationIds.isEmpty()) {
|
||||
// 过滤掉 null 值
|
||||
locationIds = locationIds.stream().filter(id -> id != null).collect(java.util.stream.Collectors.toList());
|
||||
if (!locationIds.isEmpty()) {
|
||||
List<Location> locationList
|
||||
= locationService.getLocationList(locationIds, Collections.singletonList(LocationStatus.ACTIVE.getValue()));
|
||||
log.info("getPractitionerWard - 从 locationIds 查询到的位置总数:{}", locationList != null ? locationList.size() : 0);
|
||||
|
||||
for (Location location : locationList) {
|
||||
log.info("getPractitionerWard - 位置:id={}, name={}, formEnum={}, organizationId={}",
|
||||
location.getId(), location.getName(), location.getFormEnum(), location.getOrganizationId());
|
||||
if (LocationForm.WARD.getValue().equals(location.getFormEnum())) {
|
||||
// 如果当前有选择科室,只添加当前科室的病区
|
||||
if (currentOrgId == null || currentOrgId.equals(location.getOrganizationId())) {
|
||||
wardList.add(location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 方式 2:从 orgIds 查询病区(补充查询,确保能获取到病区)
|
||||
if (orgIds != null && !orgIds.isEmpty()) {
|
||||
// 过滤掉 null 值并去重
|
||||
orgIds = orgIds.stream().filter(id -> id != null).distinct().collect(java.util.stream.Collectors.toList());
|
||||
if (!orgIds.isEmpty()) {
|
||||
log.info("getPractitionerWard - 从 orgIds 查询病区,orgIds: {}", orgIds);
|
||||
for (Long orgId : orgIds) {
|
||||
// 如果当前有选择科室,只查询当前科室的病区
|
||||
if (currentOrgId != null && !currentOrgId.equals(orgId)) {
|
||||
continue;
|
||||
}
|
||||
List<Location> orgWards = locationService.getWardList(orgId);
|
||||
log.info("getPractitionerWard - orgId: {} 查询到病区数:{}", orgId, orgWards != null ? orgWards.size() : 0);
|
||||
if (orgWards != null && !orgWards.isEmpty()) {
|
||||
wardList.addAll(orgWards);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 方式 3:如果仍然没有病区,且 currentOrgId 为空,尝试获取所有病区
|
||||
if (wardList.isEmpty() && currentOrgId == null) {
|
||||
log.info("getPractitionerWard - 尝试获取所有病区");
|
||||
List<Location> allWards = locationService.getWardList(null);
|
||||
log.info("getPractitionerWard - 所有病区数:{}", allWards != null ? allWards.size() : 0);
|
||||
if (allWards != null && !allWards.isEmpty()) {
|
||||
wardList.addAll(allWards);
|
||||
}
|
||||
}
|
||||
|
||||
// 去重:根据病区 ID 去重(因为方式 1 和方式 2 可能会查询到相同的病区)
|
||||
if (!wardList.isEmpty()) {
|
||||
wardList = wardList.stream()
|
||||
.collect(java.util.stream.Collectors.collectingAndThen(
|
||||
java.util.stream.Collectors.toCollection(() ->
|
||||
new java.util.TreeSet<>(java.util.Comparator.comparing(Location::getId))),
|
||||
ArrayList::new
|
||||
));
|
||||
}
|
||||
|
||||
log.info("getPractitionerWard - 最终病区数:{}", wardList.size());
|
||||
|
||||
// 转换为 DTO
|
||||
List<LocationDto> locationDtoList = new ArrayList<>();
|
||||
LocationDto locationDto;
|
||||
for (Location ward : wardList) {
|
||||
@@ -482,6 +551,31 @@ public class CommonServiceImpl implements ICommonService {
|
||||
BeanUtils.copyProperties(ward, locationDto);
|
||||
locationDtoList.add(locationDto);
|
||||
}
|
||||
|
||||
return locationDtoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Location列表转换为LocationDto列表
|
||||
*
|
||||
* @param locationList Location列表
|
||||
* @return LocationDto列表
|
||||
*/
|
||||
private List<LocationDto> convertToLocationDtoList(List<Location> locationList) {
|
||||
List<LocationDto> locationDtoList = new ArrayList<>();
|
||||
if (locationList == null || locationList.isEmpty()) {
|
||||
return locationDtoList;
|
||||
}
|
||||
|
||||
LocationDto locationDto;
|
||||
for (Location location : locationList) {
|
||||
// 只返回病区类型的位置
|
||||
if (LocationForm.WARD.getValue().equals(location.getFormEnum())) {
|
||||
locationDto = new LocationDto();
|
||||
BeanUtils.copyProperties(location, locationDto);
|
||||
locationDtoList.add(locationDto);
|
||||
}
|
||||
}
|
||||
return locationDtoList;
|
||||
}
|
||||
|
||||
|
||||
@@ -202,8 +202,8 @@ public class CommonAppController {
|
||||
* @return 病区列表
|
||||
*/
|
||||
@GetMapping(value = "/practitioner-ward")
|
||||
public List<LocationDto> getPractitionerWard() {
|
||||
return commonService.getPractitionerWard();
|
||||
public R<?> getPractitionerWard() {
|
||||
return R.ok(commonService.getPractitionerWard());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -193,6 +193,13 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
|
||||
DiagnosisTreatmentSelParam.setYbType(null); // 临时移除,防止HisQueryUtils处理
|
||||
}
|
||||
|
||||
// 临时保存inspectionTypeId值,手动添加带表别名的条件
|
||||
Long inspectionTypeIdValue = null;
|
||||
if (DiagnosisTreatmentSelParam != null && DiagnosisTreatmentSelParam.getInspectionTypeId() != null) {
|
||||
inspectionTypeIdValue = DiagnosisTreatmentSelParam.getInspectionTypeId();
|
||||
DiagnosisTreatmentSelParam.setInspectionTypeId(null); // 临时移除,防止HisQueryUtils处理
|
||||
}
|
||||
|
||||
// 构建查询条件
|
||||
QueryWrapper<DiagnosisTreatmentDto> queryWrapper = HisQueryUtils.buildQueryWrapper(DiagnosisTreatmentSelParam,
|
||||
searchKey, new HashSet<>(Arrays.asList("bus_no", "name", "py_str", "wb_str")), request);
|
||||
@@ -204,6 +211,13 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
|
||||
DiagnosisTreatmentSelParam.setYbType(ybTypeValue);
|
||||
}
|
||||
|
||||
// 如果需要按检验类型过滤,添加带表别名的条件
|
||||
if (inspectionTypeIdValue != null) {
|
||||
queryWrapper.eq("T1.inspection_type_id", inspectionTypeIdValue);
|
||||
// 恢复参数对象中的值
|
||||
DiagnosisTreatmentSelParam.setInspectionTypeId(inspectionTypeIdValue);
|
||||
}
|
||||
|
||||
// 分页查询
|
||||
IPage<DiagnosisTreatmentDto> diseaseTreatmentPage
|
||||
= activityDefinitionManageMapper.getDiseaseTreatmentPage(new Page<DiagnosisTreatmentDto>(pageNo, pageSize), queryWrapper);
|
||||
@@ -336,6 +350,8 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
|
||||
// 显式设置新增的字段
|
||||
activityDefinition.setSortOrder(diagnosisTreatmentUpDto.getSortOrder());
|
||||
activityDefinition.setServiceRange(diagnosisTreatmentUpDto.getServiceRange());
|
||||
// 显式设置检验类型ID
|
||||
activityDefinition.setInspectionTypeId(diagnosisTreatmentUpDto.getInspectionTypeId());
|
||||
// 显式设置划价标记(避免前端字段/类型差异导致 copyProperties 后仍为默认值)
|
||||
activityDefinition.setPricingFlag(diagnosisTreatmentUpDto.getPricingFlag());
|
||||
|
||||
@@ -483,6 +499,8 @@ public class DiagTreatMAppServiceImpl implements IDiagTreatMAppService {
|
||||
// 显式设置新增的字段
|
||||
activityDefinition.setSortOrder(diagnosisTreatmentUpDto.getSortOrder());
|
||||
activityDefinition.setServiceRange(diagnosisTreatmentUpDto.getServiceRange());
|
||||
// 显式设置检验类型ID
|
||||
activityDefinition.setInspectionTypeId(diagnosisTreatmentUpDto.getInspectionTypeId());
|
||||
|
||||
// 如果前端没有传入编码,则使用10位数基础采番
|
||||
if (StringUtils.isEmpty(activityDefinition.getBusNo())) {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.openhis.web.datadictionary.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.openhis.lab.domain.InspectionType;
|
||||
import com.openhis.lab.service.IInspectionTypeService;
|
||||
import com.openhis.web.datadictionary.appservice.IDiagTreatMAppService;
|
||||
import com.openhis.web.datadictionary.dto.DiagnosisTreatmentSelParam;
|
||||
import com.openhis.web.datadictionary.dto.DiagnosisTreatmentUpDto;
|
||||
@@ -30,6 +33,9 @@ public class DiagnosisTreatmentController {
|
||||
@Resource
|
||||
private IDiagTreatMAppService diagTreatMAppService;
|
||||
|
||||
@Resource
|
||||
private IInspectionTypeService inspectionTypeService;
|
||||
|
||||
/**
|
||||
* 诊疗目录初期查询
|
||||
*
|
||||
@@ -188,4 +194,17 @@ public class DiagnosisTreatmentController {
|
||||
public R<?> updatePricingFlag(@RequestBody List<Long> ids, @RequestParam Integer pricingFlag) {
|
||||
return diagTreatMAppService.updatePricingFlag(ids, pricingFlag);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取检验类型列表(用于下拉框)
|
||||
*
|
||||
* @return 检验类型列表
|
||||
*/
|
||||
@GetMapping("/inspection-types")
|
||||
public R<?> getInspectionTypes() {
|
||||
LambdaQueryWrapper<InspectionType> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(InspectionType::getValidFlag, 1)
|
||||
.orderByAsc(InspectionType::getSortOrder);
|
||||
return R.ok(inspectionTypeService.list(queryWrapper));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,4 +130,13 @@ public class DiagnosisTreatmentDto {
|
||||
|
||||
/** 服务范围 */
|
||||
private String serviceRange;
|
||||
|
||||
/** 检验类型ID */
|
||||
@Dict(dictTable = "inspection_type", dictCode = "id", dictText = "name", deleteFlag = "valid_flag")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long inspectionTypeId;
|
||||
private String inspectionTypeId_dictText;
|
||||
|
||||
/** 检验类型名称(用于前端 testType 字段) */
|
||||
private String testType;
|
||||
}
|
||||
|
||||
@@ -30,4 +30,7 @@ public class DiagnosisTreatmentSelParam {
|
||||
|
||||
/** 状态 */
|
||||
private Integer statusEnum;
|
||||
|
||||
/** 检验类型ID */
|
||||
private Long inspectionTypeId;
|
||||
}
|
||||
|
||||
@@ -128,4 +128,8 @@ public class DiagnosisTreatmentUpDto {
|
||||
|
||||
/** 服务范围 */
|
||||
private String serviceRange;
|
||||
|
||||
/** 检验类型ID */
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long inspectionTypeId;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.core.common.utils.MessageUtils;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.core.web.util.TenantOptionUtil;
|
||||
import com.openhis.administration.domain.Account;
|
||||
import com.openhis.administration.service.IAccountService;
|
||||
import com.openhis.administration.domain.ChargeItem;
|
||||
import com.openhis.administration.service.IChargeItemService;
|
||||
import com.openhis.common.constant.CommonConstants;
|
||||
@@ -72,6 +74,9 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
@Resource
|
||||
IChargeItemService iChargeItemService;
|
||||
|
||||
@Resource
|
||||
IAccountService iAccountService;
|
||||
|
||||
// @Resource
|
||||
// IOrganizationLocationService iOrganizationLocationService;
|
||||
@Resource
|
||||
@@ -441,9 +446,11 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
iDeviceDispenseService.deleteDeviceDispense(adviceSaveDto.getRequestId());
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix: 跳过耗材的库存校验(耗材的库存校验逻辑不同)
|
||||
List<AdviceSaveDto> needCheckList = adviceSaveList.stream()
|
||||
.filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType())
|
||||
&& !ItemType.ACTIVITY.getValue().equals(e.getAdviceType()))
|
||||
&& !ItemType.ACTIVITY.getValue().equals(e.getAdviceType())
|
||||
&& !ItemType.DEVICE.getValue().equals(e.getAdviceType())) // 排除耗材
|
||||
.collect(Collectors.toList());
|
||||
// 校验库存
|
||||
String tipRes = adviceUtils.checkInventory(needCheckList);
|
||||
@@ -778,7 +785,27 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
chargeItem.setServiceId(deviceRequest.getId()); // 医疗服务ID
|
||||
chargeItem.setProductTable(adviceSaveDto.getAdviceTableName());// 产品所在表
|
||||
chargeItem.setProductId(adviceSaveDto.getAdviceDefinitionId());// 收费项id
|
||||
chargeItem.setAccountId(adviceSaveDto.getAccountId());// 关联账户ID
|
||||
// 🔧 Bug Fix: 如果accountId为null,从就诊中获取账户ID,如果没有则自动创建
|
||||
Long accountId = adviceSaveDto.getAccountId();
|
||||
if (accountId == null) {
|
||||
// 尝试从患者就诊中获取默认账户ID(自费账户)
|
||||
Account selfAccount = iAccountService.getSelfAccount(adviceSaveDto.getEncounterId());
|
||||
if (selfAccount != null) {
|
||||
accountId = selfAccount.getId();
|
||||
} else {
|
||||
// 自动创建自费账户
|
||||
Account newAccount = new Account();
|
||||
newAccount.setPatientId(adviceSaveDto.getPatientId());
|
||||
newAccount.setEncounterId(adviceSaveDto.getEncounterId());
|
||||
newAccount.setContractNo(CommonConstants.BusinessName.DEFAULT_CONTRACT_NO);
|
||||
newAccount.setTypeCode(AccountType.PERSONAL_CASH_ACCOUNT.getCode());
|
||||
newAccount.setBalanceAmount(BigDecimal.ZERO);
|
||||
newAccount.setStatusEnum(AccountStatus.ACTIVE.getValue());
|
||||
newAccount.setEncounterFlag(Whether.YES.getValue());
|
||||
accountId = iAccountService.saveAccountByRegister(newAccount);
|
||||
}
|
||||
}
|
||||
chargeItem.setAccountId(accountId);// 关联账户ID
|
||||
chargeItem.setConditionId(adviceSaveDto.getConditionId()); // 诊断id
|
||||
chargeItem.setEncounterDiagnosisId(adviceSaveDto.getEncounterDiagnosisId()); // 就诊诊断id
|
||||
chargeItem.setDispenseId(dispenseId); // 发放ID
|
||||
|
||||
@@ -351,6 +351,8 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
|
||||
encounterDiagnosis.setName(saveDiagnosisChildParam.getName());
|
||||
encounterDiagnosis.setTenantId(tenantId);
|
||||
encounterDiagnosis.setLongTermFlag(saveDiagnosisChildParam.getLongTermFlag());
|
||||
encounterDiagnosis.setOnsetDate(saveDiagnosisChildParam.getOnsetDate());
|
||||
encounterDiagnosis.setDiagnosisTime(saveDiagnosisChildParam.getDiagnosisTime());
|
||||
if(encounterDiagnosis.getCreateBy() == null){
|
||||
encounterDiagnosis.setCreateBy(username);
|
||||
}
|
||||
@@ -377,6 +379,8 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
|
||||
encounterDiagnosis.setName(saveDiagnosisChildParam.getName());
|
||||
encounterDiagnosis.setTenantId(tenantId);
|
||||
encounterDiagnosis.setLongTermFlag(saveDiagnosisChildParam.getLongTermFlag());
|
||||
encounterDiagnosis.setOnsetDate(saveDiagnosisChildParam.getOnsetDate());
|
||||
encounterDiagnosis.setDiagnosisTime(saveDiagnosisChildParam.getDiagnosisTime());
|
||||
if(encounterDiagnosis.getCreateBy() == null){
|
||||
encounterDiagnosis.setCreateBy(username);
|
||||
}
|
||||
|
||||
@@ -16,10 +16,12 @@ import java.util.Date;
|
||||
import java.sql.Timestamp;
|
||||
import com.openhis.common.enums.BindingType;
|
||||
import com.openhis.common.enums.EncounterStatus;
|
||||
import com.openhis.document.domain.DocRecord;
|
||||
import com.openhis.document.domain.Emr;
|
||||
import com.openhis.document.domain.EmrDetail;
|
||||
import com.openhis.document.domain.EmrDict;
|
||||
import com.openhis.document.domain.EmrTemplate;
|
||||
import com.openhis.document.service.IDocRecordService;
|
||||
import com.openhis.document.service.IEmrDetailService;
|
||||
import com.openhis.document.service.IEmrDictService;
|
||||
import com.openhis.document.service.IEmrService;
|
||||
@@ -54,6 +56,9 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
||||
@Resource
|
||||
IEmrDictService emrDictService;
|
||||
|
||||
@Resource
|
||||
IDocRecordService docRecordService;
|
||||
|
||||
@Resource
|
||||
private EncounterMapper encounterMapper;
|
||||
|
||||
@@ -128,14 +133,33 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
||||
|
||||
/**
|
||||
* 获取病历详情
|
||||
* 同时检查门诊病历(emr表)和住院病历(doc_record表)
|
||||
*
|
||||
* @param encounterId 就诊id
|
||||
* @return 病历详情
|
||||
*/
|
||||
@Override
|
||||
public R<?> getEmrDetail(Long encounterId) {
|
||||
// 先查询门诊病历(emr表)
|
||||
Emr emrDetail = emrService.getOne(new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounterId));
|
||||
return R.ok(emrDetail);
|
||||
if (emrDetail != null) {
|
||||
return R.ok(emrDetail);
|
||||
}
|
||||
|
||||
// 如果门诊病历为空,检查住院病历(doc_record表)
|
||||
DocRecord docRecord = docRecordService.getOne(
|
||||
new LambdaQueryWrapper<DocRecord>()
|
||||
.eq(DocRecord::getEncounterId, encounterId)
|
||||
.orderByDesc(DocRecord::getCreateTime)
|
||||
.last("LIMIT 1")
|
||||
);
|
||||
if (docRecord != null) {
|
||||
// 住院病历存在,也返回数据
|
||||
return R.ok(docRecord);
|
||||
}
|
||||
|
||||
// 都没有病历
|
||||
return R.ok(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -230,35 +230,67 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer
|
||||
*/
|
||||
@Override
|
||||
public R<?> cancelEncounter(Long encounterId) {
|
||||
//1.判断是否已经产生业务,如医生已经开有病历、处方、诊断、检验检查或相关项目已收费、执行等,
|
||||
//如果有则提示:需要医生删除、作废、退费才能【取消接诊】。
|
||||
//1.1病历
|
||||
Object emrDetailResult = iDoctorStationEmrAppService.getEmrDetail(encounterId).getData();
|
||||
try {
|
||||
//1.判断是否已经产生业务,如医生已经开有病历、处方、诊断、检验检查或相关项目已收费、执行等,
|
||||
//如果有则提示:需要医生删除、作废、退费才能【取消接诊】。
|
||||
|
||||
//1.2诊断
|
||||
Object diagnosisResult = iDoctorStationDiagnosisAppService.getEncounterDiagnosis(encounterId).getData();
|
||||
//1.1病历
|
||||
Object emrDetailResult = null;
|
||||
try {
|
||||
emrDetailResult = iDoctorStationEmrAppService.getEmrDetail(encounterId).getData();
|
||||
} catch (Exception e) {
|
||||
log.debug("获取病历信息失败: {}", e.getMessage());
|
||||
}
|
||||
|
||||
//1.3处方
|
||||
Object adviceResult = iDoctorStationAdviceAppService.getRequestBaseInfo(encounterId).getData();
|
||||
//1.2诊断
|
||||
Object diagnosisResult = null;
|
||||
try {
|
||||
diagnosisResult = iDoctorStationDiagnosisAppService.getEncounterDiagnosis(encounterId).getData();
|
||||
} catch (Exception e) {
|
||||
log.debug("获取诊断信息失败: {}", e.getMessage());
|
||||
}
|
||||
|
||||
//1.4中医诊断、处方
|
||||
Map<?,?> tcmDiagnosisResult = (Map<?,?>) iDoctorStationChineseMedicalAppService.getTcmEncounterDiagnosis(encounterId).getData();
|
||||
Object symptom = tcmDiagnosisResult.get("symptom");
|
||||
Object illness = tcmDiagnosisResult.get("illness");
|
||||
Object tcmPrescriptionResult = iDoctorStationChineseMedicalAppService.getTcmRequestBaseInfo(encounterId).getData();
|
||||
//1.3处方
|
||||
Object adviceResult = null;
|
||||
try {
|
||||
adviceResult = iDoctorStationAdviceAppService.getRequestBaseInfo(encounterId).getData();
|
||||
} catch (Exception e) {
|
||||
log.debug("获取处方信息失败: {}", e.getMessage());
|
||||
}
|
||||
|
||||
boolean isEmpty = ObjectUtil.isAllEmpty(emrDetailResult, diagnosisResult, adviceResult, symptom,illness, tcmPrescriptionResult);
|
||||
//1.4中医诊断、处方
|
||||
Object symptom = null;
|
||||
Object illness = null;
|
||||
Object tcmPrescriptionResult = null;
|
||||
|
||||
if (!isEmpty) {
|
||||
return R.fail();
|
||||
try {
|
||||
Map<?,?> tcmDiagnosisResult = (Map<?,?>) iDoctorStationChineseMedicalAppService.getTcmEncounterDiagnosis(encounterId).getData();
|
||||
if (tcmDiagnosisResult != null) {
|
||||
symptom = tcmDiagnosisResult.get("symptom");
|
||||
illness = tcmDiagnosisResult.get("illness");
|
||||
}
|
||||
tcmPrescriptionResult = iDoctorStationChineseMedicalAppService.getTcmRequestBaseInfo(encounterId).getData();
|
||||
} catch (Exception e) {
|
||||
// 中医模块可能未启用或返回异常,忽略
|
||||
log.debug("获取中医信息失败,可能未配置中医模块: {}", e.getMessage());
|
||||
}
|
||||
|
||||
boolean isEmpty = ObjectUtil.isAllEmpty(emrDetailResult, diagnosisResult, adviceResult, symptom, illness, tcmPrescriptionResult);
|
||||
|
||||
if (!isEmpty) {
|
||||
return R.fail("该患者已产生业务数据(病历、诊断、处方等),无法直接取消接诊。请先删除相关数据后再操作。");
|
||||
}
|
||||
|
||||
//2.取消接诊,患者重新回到患者队列待诊中
|
||||
int update = encounterMapper.update(null,
|
||||
new LambdaUpdateWrapper<Encounter>().eq(Encounter::getId, encounterId)
|
||||
.set(Encounter::getStatusEnum, EncounterStatus.PLANNED.getValue())
|
||||
.set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.TRIAGED.getValue()));
|
||||
return update > 0 ? R.ok("取消接诊成功") : R.fail("取消接诊失败,请刷新后重试");
|
||||
} catch (Exception e) {
|
||||
log.error("取消接诊时发生错误,encounterId={}", encounterId, e);
|
||||
return R.fail("取消接诊失败:" + e.getMessage());
|
||||
}
|
||||
|
||||
//2.取消接诊,患者重新回到患者队列待诊中
|
||||
int update = encounterMapper.update(null,
|
||||
new LambdaUpdateWrapper<Encounter>().eq(Encounter::getId, encounterId)
|
||||
.set(Encounter::getStatusEnum, EncounterStatus.PLANNED.getValue())
|
||||
.set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.TRIAGED.getValue()));
|
||||
return update > 0 ? R.ok() : R.fail();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,8 @@ import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||
import com.fasterxml.jackson.annotation.Nulls;
|
||||
|
||||
/**
|
||||
* 医嘱保存 dto
|
||||
@@ -80,6 +82,7 @@ public class AdviceSaveDto {
|
||||
private BigDecimal unitPrice;
|
||||
|
||||
/** 总价 */
|
||||
@JsonSetter(nulls = Nulls.AS_EMPTY)
|
||||
private BigDecimal totalPrice;
|
||||
|
||||
/** 费用定价主表ID */
|
||||
@@ -250,9 +253,22 @@ public class AdviceSaveDto {
|
||||
*/
|
||||
public AdviceSaveDto() {
|
||||
this.chineseHerbsDoseQuantity = new BigDecimal("1");
|
||||
this.therapyEnum = TherapyTimeType.TEMPORARY.getValue();
|
||||
// 默认设置为长期医嘱,但前端应该明确传递正确的值
|
||||
this.therapyEnum = TherapyTimeType.LONG_TERM.getValue();
|
||||
this.practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
||||
this.founderOrgId = SecurityUtils.getLoginUser().getOrgId(); // 开方人科室
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔧 Bug Fix: Custom setter for totalPrice to handle NaN and invalid values
|
||||
* Prevents JSON parse errors when frontend sends NaN or invalid BigDecimal values
|
||||
*/
|
||||
public void setTotalPrice(BigDecimal totalPrice) {
|
||||
if (totalPrice == null || totalPrice.compareTo(BigDecimal.ZERO) < 0) {
|
||||
this.totalPrice = BigDecimal.ZERO;
|
||||
} else {
|
||||
this.totalPrice = totalPrice;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.openhis.common.annotation.Dict;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 诊断查询 dto
|
||||
*
|
||||
@@ -79,4 +81,14 @@ public class DiagnosisQueryDto {
|
||||
*/
|
||||
private String diagnosisDesc;
|
||||
|
||||
/**
|
||||
* 发病日期
|
||||
*/
|
||||
private Date onsetDate;
|
||||
|
||||
/**
|
||||
* 诊断日期
|
||||
*/
|
||||
private Date diagnosisTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -174,4 +174,12 @@ public interface DoctorStationAdviceAppMapper {
|
||||
List<ProofAndTestResultDto> getProofAndTestResult(@Param("encounterId") Long encounterId,
|
||||
@Param("status") Integer status, @Param("typeEnum") Integer typeEnum);
|
||||
|
||||
/**
|
||||
* 获取就诊的默认账户ID
|
||||
*
|
||||
* @param encounterId 就诊ID
|
||||
* @return 默认账户ID,如果没有则返回null
|
||||
*/
|
||||
Long getDefaultAccountId(@Param("encounterId") Long encounterId);
|
||||
|
||||
}
|
||||
|
||||
@@ -98,11 +98,14 @@ public class AdviceUtils {
|
||||
for (AdviceInventoryDto inventoryDto : adviceInventory) {
|
||||
// 匹配条件:adviceDefinitionId, adviceTableName, locationId, lotNumber 同时相等
|
||||
// 如果选择了具体的批次号,校验库存时需要加上批次号的匹配条件
|
||||
// 🔧 Bug #177 修复:添加容错处理,如果 adviceTableName 为空则跳过该项匹配
|
||||
boolean lotNumberMatch = StringUtils.isEmpty(saveDto.getLotNumber())
|
||||
|| saveDto.getLotNumber().equals(inventoryDto.getLotNumber());
|
||||
boolean tableNameMatch = StringUtils.isEmpty(saveDto.getAdviceTableName())
|
||||
|| inventoryDto.getItemTable().equals(saveDto.getAdviceTableName());
|
||||
// if (saveDto.)
|
||||
if (inventoryDto.getItemId().equals(saveDto.getAdviceDefinitionId())
|
||||
&& inventoryDto.getItemTable().equals(saveDto.getAdviceTableName())
|
||||
&& tableNameMatch
|
||||
&& inventoryDto.getLocationId().equals(saveDto.getLocationId()) && lotNumberMatch) {
|
||||
matched = true;
|
||||
// 检查库存是否充足
|
||||
|
||||
@@ -245,15 +245,37 @@ public class DocDefinitionAppServiceImpl implements IDocDefinitionAppService {
|
||||
public R<?> getTreeList(DocDefinitonParam param) {
|
||||
// 1. 获取当前登录用户的医院ID(避免跨医院查询)
|
||||
Long hospitalId = SecurityUtils.getLoginUser().getHospitalId();
|
||||
Long organizationId = param.getOrganizationId();
|
||||
List<Integer> useRanges = param.getUseRanges();
|
||||
|
||||
log.info("获取文书定义树形列表 - 请求参数: hospitalId={}, organizationId={}, useRanges={}, name={}, primaryMenuEnum={}",
|
||||
hospitalId, organizationId, useRanges, param.getName(), param.getPrimaryMenuEnum());
|
||||
|
||||
if (hospitalId == null) {
|
||||
log.warn("当前登录用户未关联医院ID,将使用默认值");
|
||||
// 设置默认医院ID为1(或其他合适的默认值)
|
||||
hospitalId = 1L;
|
||||
}
|
||||
|
||||
if (organizationId == null || organizationId == 0) {
|
||||
log.warn("organizationId为空或0,将跳过医院过滤和使用范围过滤");
|
||||
}
|
||||
|
||||
if (useRanges == null || useRanges.isEmpty()) {
|
||||
log.warn("useRanges为空,可能返回所有使用范围的文书");
|
||||
}
|
||||
|
||||
// 2. 数据库查询文书定义列表
|
||||
List<DocDefinitionDto> docList = docDefinitionAppMapper.getDefinationList(param.getUseRanges(),
|
||||
param.getOrganizationId(), hospitalId, param.getName(), param.getPrimaryMenuEnum());
|
||||
List<DocDefinitionDto> docList = docDefinitionAppMapper.getDefinationList(useRanges,
|
||||
organizationId, hospitalId, param.getName(), param.getPrimaryMenuEnum());
|
||||
|
||||
log.info("获取文书定义树形列表 - 查询结果: 记录数={}", docList != null ? docList.size() : 0);
|
||||
if (docList != null && !docList.isEmpty()) {
|
||||
for (DocDefinitionDto doc : docList) {
|
||||
log.debug("文书: id={}, name={}, useRangeEnum={}, hospitalId={}",
|
||||
doc.getId(), doc.getName(), doc.getUseRangeEnum(), doc.getHospitalId());
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 构建树形结构(空列表时返回空树,避免空指针)
|
||||
List<DirectoryNode> treeNodes = new ArrayList<>();
|
||||
|
||||
@@ -106,7 +106,9 @@ public class DocDefinitionController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/treeList")
|
||||
public R<?> getTreeList(DocDefinitonParam docDefinitonParam) {
|
||||
public R<?> getTreeList(DocDefinitonParam docDefinitonParam,
|
||||
@RequestParam(value = "useRanges", required = false) List<Integer> useRanges) {
|
||||
docDefinitonParam.setUseRanges(useRanges);
|
||||
return iDocDefinitionAppService.getTreeList(docDefinitonParam);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,13 @@ import com.core.common.utils.SecurityUtils;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.openhis.administration.domain.Encounter;
|
||||
import com.openhis.administration.domain.EncounterLocation;
|
||||
import com.openhis.administration.domain.EncounterParticipant;
|
||||
import com.openhis.administration.domain.Practitioner;
|
||||
import com.openhis.administration.service.IEncounterLocationService;
|
||||
import com.openhis.administration.service.IEncounterParticipantService;
|
||||
import com.openhis.administration.service.IEncounterService;
|
||||
import com.openhis.administration.service.ILocationService;
|
||||
import com.openhis.administration.service.IPractitionerService;
|
||||
import com.openhis.common.constant.CommonConstants;
|
||||
import com.openhis.common.enums.*;
|
||||
import com.openhis.common.utils.EnumUtils;
|
||||
@@ -40,8 +43,10 @@ import com.openhis.web.inhospitalnursestation.mapper.ATDManageAppMapper;
|
||||
import com.openhis.workflow.domain.ServiceRequest;
|
||||
import com.openhis.workflow.service.IServiceRequestService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -53,6 +58,7 @@ import java.util.stream.Stream;
|
||||
* @author zwh
|
||||
* @date 2025-07-28
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
|
||||
@@ -92,6 +98,9 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
@Resource
|
||||
private IServiceRequestService serviceRequestService;
|
||||
|
||||
@Resource
|
||||
private IPractitionerService practitionerService;
|
||||
|
||||
/**
|
||||
* 入出转管理页面初始化
|
||||
*
|
||||
@@ -212,24 +221,150 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
*/
|
||||
@Override
|
||||
public R<?> getAdmissionPatientInfo(Long encounterId) {
|
||||
// 查询住院患者详细信息
|
||||
log.info("========== 查询患者信息 - encounterId: {} ==========", encounterId);
|
||||
Integer active = EncounterActivityStatus.ACTIVE.getValue();
|
||||
String primaryNurse = ParticipantType.PRIMARY_NURSE.getCode();
|
||||
String attendingDoctor = ParticipantType.ATTENDING_DOCTOR.getCode();
|
||||
String admittingDoctor = ParticipantType.ADMITTING_DOCTOR.getCode();
|
||||
String chiefDoctor = ParticipantType.CHIEF_DOCTOR.getCode();
|
||||
log.info("查询参数 - encounterId: {}, active: {} (type: {}), primaryNurse: {} (type: {}), attendingDoctor: {} (type: {}), admittingDoctor: {} (type: {}), chiefDoctor: {} (type: {})",
|
||||
encounterId, active, active.getClass().getSimpleName(),
|
||||
primaryNurse, primaryNurse.getClass().getSimpleName(),
|
||||
attendingDoctor, attendingDoctor.getClass().getSimpleName(),
|
||||
admittingDoctor, admittingDoctor.getClass().getSimpleName(),
|
||||
chiefDoctor, chiefDoctor.getClass().getSimpleName());
|
||||
|
||||
// 先通过简单的 SQL 查询患者基本信息
|
||||
AdmissionPatientInfoDto admissionPatientInfoDto
|
||||
= atdManageAppMapper.selectAdmissionPatientInfo(encounterId, EncounterActivityStatus.ACTIVE.getValue(),
|
||||
= atdManageAppMapper.selectAdmissionPatientInfo(encounterId, active,
|
||||
LocationForm.WARD.getValue(), LocationForm.HOUSE.getValue(), LocationForm.BED.getValue(),
|
||||
ParticipantType.PRIMARY_NURSE.getCode(), ParticipantType.ATTENDING_DOCTOR.getCode(),
|
||||
ParticipantType.ADMITTING_DOCTOR.getCode(), ParticipantType.CHIEF_DOCTOR.getCode());
|
||||
// 年龄
|
||||
if (admissionPatientInfoDto.getBirthDate() != null) {
|
||||
admissionPatientInfoDto.setAge(AgeCalculatorUtil.getAge(admissionPatientInfoDto.getBirthDate()));
|
||||
primaryNurse, attendingDoctor, admittingDoctor, chiefDoctor);
|
||||
|
||||
// 从 EncounterParticipant 表手动获取医生护士信息
|
||||
List<EncounterParticipant> participantList = encounterParticipantService.getEncounterParticipantList(encounterId);
|
||||
log.info("从 EncounterParticipant 获取到 {} 条记录", participantList.size());
|
||||
|
||||
// 调试:打印所有 participant 的详细信息
|
||||
for (EncounterParticipant ep : participantList) {
|
||||
log.info("调试 - typeCode: '{}', practitionerId: {}, statusEnum: {}, deleteFlag: '{}'",
|
||||
ep.getTypeCode(), ep.getPractitionerId(), ep.getStatusEnum(), ep.getDeleteFlag());
|
||||
}
|
||||
// 性别
|
||||
admissionPatientInfoDto.setGenderEnum_enumText(
|
||||
EnumUtils.getInfoByValue(AdministrativeGender.class, admissionPatientInfoDto.getGenderEnum()));
|
||||
// 病情
|
||||
admissionPatientInfoDto.setPriorityEnum_enumText(
|
||||
EnumUtils.getInfoByValue(PriorityLevel.class, admissionPatientInfoDto.getPriorityEnum()));
|
||||
// 获取入院体征
|
||||
getAdmissionSigns(encounterId, admissionPatientInfoDto);
|
||||
|
||||
// 查找各个角色 - 使用 Integer 类型进行比较
|
||||
Integer primaryNurseValue = ParticipantType.PRIMARY_NURSE.getValue();
|
||||
Integer attendingDoctorValue = ParticipantType.ATTENDING_DOCTOR.getValue();
|
||||
Integer admittingDoctorValue = ParticipantType.ADMITTING_DOCTOR.getValue();
|
||||
Integer chiefDoctorValue = ParticipantType.CHIEF_DOCTOR.getValue();
|
||||
|
||||
log.info("枚举值 - primaryNurse: {} ({})", primaryNurseValue, primaryNurse);
|
||||
log.info("枚举值 - attendingDoctor: {} ({})", attendingDoctorValue, attendingDoctor);
|
||||
log.info("枚举值 - admittingDoctor: {} ({})", admittingDoctorValue, admittingDoctor);
|
||||
log.info("枚举值 - chiefDoctor: {} ({})", chiefDoctorValue, chiefDoctor);
|
||||
|
||||
// 查找各个角色
|
||||
Long primaryNurseId = null;
|
||||
String primaryNurseName = null;
|
||||
Long attendingDoctorId = null;
|
||||
String attendingDoctorName = null;
|
||||
Long admittingDoctorId = null;
|
||||
String admittingDoctorName = null;
|
||||
Long chiefDoctorId = null;
|
||||
String chiefDoctorName = null;
|
||||
|
||||
for (EncounterParticipant ep : participantList) {
|
||||
if (ep.getStatusEnum() == null || !ep.getStatusEnum().equals(active)) {
|
||||
log.info("跳过 - statusEnum: {} vs active: {}", ep.getStatusEnum(), active);
|
||||
continue;
|
||||
}
|
||||
if (ep.getTypeCode() == null) {
|
||||
log.info("跳过 - typeCode 为空");
|
||||
continue;
|
||||
}
|
||||
|
||||
// 尝试将 typeCode 转换为 Integer 进行比较
|
||||
Integer typeCodeValue = null;
|
||||
try {
|
||||
typeCodeValue = Integer.parseInt(ep.getTypeCode().trim());
|
||||
} catch (NumberFormatException e) {
|
||||
log.warn("typeCode 无法转换为 Integer: {}", ep.getTypeCode());
|
||||
}
|
||||
|
||||
log.info("检查 typeCode: {} (Integer: {}) vs primaryNurseValue: {}, attendingDoctorValue: {}, admittingDoctorValue: {}, chiefDoctorValue: {}",
|
||||
ep.getTypeCode(), typeCodeValue, primaryNurseValue, attendingDoctorValue, admittingDoctorValue, chiefDoctorValue);
|
||||
|
||||
// 根据 typeCode 的 Integer 值匹配并获取 practitioner 名称
|
||||
if (typeCodeValue != null && typeCodeValue.equals(primaryNurseValue)) {
|
||||
primaryNurseId = ep.getPractitionerId();
|
||||
// 查询 practitioner 名称
|
||||
if (primaryNurseId != null) {
|
||||
Practitioner practitioner = practitionerService.getById(primaryNurseId);
|
||||
if (practitioner != null) {
|
||||
primaryNurseName = practitioner.getName();
|
||||
}
|
||||
}
|
||||
log.info("找到责任护士 - id: {}, name: {}", primaryNurseId, primaryNurseName);
|
||||
} else if (typeCodeValue != null && typeCodeValue.equals(attendingDoctorValue)) {
|
||||
attendingDoctorId = ep.getPractitionerId();
|
||||
if (attendingDoctorId != null) {
|
||||
Practitioner practitioner = practitionerService.getById(attendingDoctorId);
|
||||
if (practitioner != null) {
|
||||
attendingDoctorName = practitioner.getName();
|
||||
}
|
||||
}
|
||||
log.info("找到主治医生 - id: {}, name: {}", attendingDoctorId, attendingDoctorName);
|
||||
} else if (typeCodeValue != null && typeCodeValue.equals(admittingDoctorValue)) {
|
||||
admittingDoctorId = ep.getPractitionerId();
|
||||
if (admittingDoctorId != null) {
|
||||
Practitioner practitioner = practitionerService.getById(admittingDoctorId);
|
||||
if (practitioner != null) {
|
||||
admittingDoctorName = practitioner.getName();
|
||||
}
|
||||
}
|
||||
log.info("找到入院医生 - id: {}, name: {}", admittingDoctorId, admittingDoctorName);
|
||||
} else if (typeCodeValue != null && typeCodeValue.equals(chiefDoctorValue)) {
|
||||
chiefDoctorId = ep.getPractitionerId();
|
||||
if (chiefDoctorId != null) {
|
||||
Practitioner practitioner = practitionerService.getById(chiefDoctorId);
|
||||
if (practitioner != null) {
|
||||
chiefDoctorName = practitioner.getName();
|
||||
}
|
||||
}
|
||||
log.info("找到主任医生 - id: {}, name: {}", chiefDoctorId, chiefDoctorName);
|
||||
} else {
|
||||
log.info("未匹配到任何角色 typeCode: {} (value: {})", ep.getTypeCode(), typeCodeValue);
|
||||
}
|
||||
}
|
||||
|
||||
// 手动设置医生护士信息到 DTO
|
||||
if (admissionPatientInfoDto != null) {
|
||||
admissionPatientInfoDto.setPrimaryNurseId(primaryNurseId);
|
||||
admissionPatientInfoDto.setPrimaryNurseName(primaryNurseName);
|
||||
admissionPatientInfoDto.setAttendingDoctorId(attendingDoctorId);
|
||||
admissionPatientInfoDto.setAttendingDoctorName(attendingDoctorName);
|
||||
admissionPatientInfoDto.setAdmittingDoctorId(admittingDoctorId);
|
||||
admissionPatientInfoDto.setAdmittingDoctorName(admittingDoctorName);
|
||||
admissionPatientInfoDto.setChiefDoctorId(chiefDoctorId);
|
||||
admissionPatientInfoDto.setChiefDoctorName(chiefDoctorName);
|
||||
|
||||
// 年龄
|
||||
if (admissionPatientInfoDto.getBirthDate() != null) {
|
||||
admissionPatientInfoDto.setAge(AgeCalculatorUtil.getAge(admissionPatientInfoDto.getBirthDate()));
|
||||
}
|
||||
// 性别
|
||||
admissionPatientInfoDto.setGenderEnum_enumText(
|
||||
EnumUtils.getInfoByValue(AdministrativeGender.class, admissionPatientInfoDto.getGenderEnum()));
|
||||
// 病情
|
||||
admissionPatientInfoDto.setPriorityEnum_enumText(
|
||||
EnumUtils.getInfoByValue(PriorityLevel.class, admissionPatientInfoDto.getPriorityEnum()));
|
||||
// 获取入院体征
|
||||
getAdmissionSigns(encounterId, admissionPatientInfoDto);
|
||||
}
|
||||
|
||||
log.info("查询结果 - admittingDoctorId: {}, attendingDoctorId: {}, chiefDoctorId: {}, primaryNurseId: {}",
|
||||
admissionPatientInfoDto != null ? admissionPatientInfoDto.getAdmittingDoctorId() : "null",
|
||||
admissionPatientInfoDto != null ? admissionPatientInfoDto.getAttendingDoctorId() : "null",
|
||||
admissionPatientInfoDto != null ? admissionPatientInfoDto.getChiefDoctorId() : "null",
|
||||
admissionPatientInfoDto != null ? admissionPatientInfoDto.getPrimaryNurseId() : "null");
|
||||
return R.ok(admissionPatientInfoDto);
|
||||
}
|
||||
|
||||
@@ -283,7 +418,9 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> admissionBedAssignment(AdmissionPatientInfoDto admissionPatientInfoDto) {
|
||||
log.info("===== admissionBedAssignment 开始 =====");
|
||||
|
||||
// 住院id
|
||||
Long encounterId = admissionPatientInfoDto.getEncounterId();
|
||||
@@ -297,35 +434,58 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
Long targetBedId = admissionPatientInfoDto.getTargetBedId();
|
||||
|
||||
// 进入编辑患者信息,不更换床位
|
||||
if (Whether.YES.getCode().equals(admissionPatientInfoDto.getEditFlag())) {
|
||||
if ("1".equals(admissionPatientInfoDto.getEditFlag())) {
|
||||
log.info("编辑模式 - encounterId: {}, admittingDoctorId: {}, attendingDoctorId: {}, chiefDoctorId: {}, primaryNurseId: {}",
|
||||
encounterId, admissionPatientInfoDto.getAdmittingDoctorId(), admissionPatientInfoDto.getAttendingDoctorId(),
|
||||
admissionPatientInfoDto.getChiefDoctorId(), admissionPatientInfoDto.getPrimaryNurseId());
|
||||
// 更新患者病情(如果提供了)
|
||||
if (admissionPatientInfoDto.getPriorityEnum() != null) {
|
||||
// 更新患者病情
|
||||
encounterService.updatePriorityEnumById(encounterId, admissionPatientInfoDto.getPriorityEnum());
|
||||
// 将之前的住院参与者更新为已完成(如果存在的话)
|
||||
encounterParticipantService.updateEncounterParticipantsStatus(encounterId);
|
||||
// 更新住院参与者
|
||||
// 住院医生
|
||||
}
|
||||
// 将之前的住院参与者更新为已完成(如果存在的话)
|
||||
encounterParticipantService.updateEncounterParticipantsStatus(encounterId);
|
||||
// 更新住院参与者
|
||||
// 住院医生(必须填写)
|
||||
if (admissionPatientInfoDto.getAdmittingDoctorId() != null) {
|
||||
encounterParticipantService.creatEncounterParticipants(encounterId, startTime,
|
||||
admissionPatientInfoDto.getAdmittingDoctorId(), ParticipantType.ADMITTING_DOCTOR.getCode());
|
||||
// 责任护士
|
||||
}
|
||||
// 责任护士(必须填写)
|
||||
if (admissionPatientInfoDto.getPrimaryNurseId() != null) {
|
||||
encounterParticipantService.creatEncounterParticipants(encounterId, startTime,
|
||||
admissionPatientInfoDto.getPrimaryNurseId(), ParticipantType.PRIMARY_NURSE.getCode());
|
||||
if (admissionPatientInfoDto.getAttendingDoctorId() != null) {
|
||||
// 主治医生
|
||||
encounterParticipantService.creatEncounterParticipants(encounterId, startTime,
|
||||
admissionPatientInfoDto.getAttendingDoctorId(), ParticipantType.ATTENDING_DOCTOR.getCode());
|
||||
}
|
||||
if (admissionPatientInfoDto.getChiefDoctorId() != null) {
|
||||
// 主任医生
|
||||
encounterParticipantService.creatEncounterParticipants(encounterId, startTime,
|
||||
admissionPatientInfoDto.getChiefDoctorId(), ParticipantType.CHIEF_DOCTOR.getCode());
|
||||
}
|
||||
}
|
||||
// 更新入院体征
|
||||
saveOrUpdateAdmissionSigns(encounterId, admissionPatientInfoDto, startTime);
|
||||
// 主治医生(可选)
|
||||
if (admissionPatientInfoDto.getAttendingDoctorId() != null) {
|
||||
encounterParticipantService.creatEncounterParticipants(encounterId, startTime,
|
||||
admissionPatientInfoDto.getAttendingDoctorId(), ParticipantType.ATTENDING_DOCTOR.getCode());
|
||||
}
|
||||
// 主任医生(可选)
|
||||
if (admissionPatientInfoDto.getChiefDoctorId() != null) {
|
||||
encounterParticipantService.creatEncounterParticipants(encounterId, startTime,
|
||||
admissionPatientInfoDto.getChiefDoctorId(), ParticipantType.CHIEF_DOCTOR.getCode());
|
||||
}
|
||||
// 保存后立即查询确认数据
|
||||
List<EncounterParticipant> savedParticipants = encounterParticipantService.getEncounterParticipantList(encounterId);
|
||||
log.info("保存后查询参与者 - encounterId: {}, 数量: {}", encounterId, savedParticipants.size());
|
||||
for (EncounterParticipant ep : savedParticipants) {
|
||||
log.info("参与者详情 - typeCode: {}, practitionerId: {}, statusEnum: {}",
|
||||
ep.getTypeCode(), ep.getPractitionerId(), ep.getStatusEnum());
|
||||
}
|
||||
// 更新入院体征(在事务外执行,避免影响参与者数据保存)
|
||||
try {
|
||||
saveOrUpdateAdmissionSigns(encounterId, admissionPatientInfoDto, startTime);
|
||||
} catch (Exception e) {
|
||||
log.error("保存入院体征失败,但不影响参与者数据", e);
|
||||
}
|
||||
return R.ok("患者信息更新成功");
|
||||
}
|
||||
|
||||
// 新分配床位时,校验床位信息
|
||||
if (targetBedId == null || admissionPatientInfoDto.getTargetHouseId() == null) {
|
||||
return R.fail("床位分配失败,请选择有效的床位");
|
||||
}
|
||||
|
||||
// 判断患者是否已经在床
|
||||
if (oldBedId != null) {
|
||||
// 判断目标床位是否已经被占用
|
||||
@@ -421,8 +581,12 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
if (result == 0) {
|
||||
return R.fail("床位分配失败,请联系管理员");
|
||||
}
|
||||
// 保存入院体征
|
||||
saveOrUpdateAdmissionSigns(encounterId, admissionPatientInfoDto, startTime);
|
||||
// 保存入院体征(在事务外执行,避免影响参与者数据保存)
|
||||
try {
|
||||
saveOrUpdateAdmissionSigns(encounterId, admissionPatientInfoDto, startTime);
|
||||
} catch (Exception e) {
|
||||
log.error("保存入院体征失败,但不影响参与者数据", e);
|
||||
}
|
||||
return R.ok("床位分配成功");
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,8 @@ public class PatientHomeAppServiceImpl implements IPatientHomeAppService {
|
||||
|
||||
// 分页查询,查询患者信息
|
||||
IPage<PatientHomeDto> patientHomeInfoPage = patientHomeAppMapper.getPage(new Page<>(pageNo, pageSize),
|
||||
patientHomeSearchParam.getStatusEnum(), patientHomeSearchParam.getPatientId(), searchKey, queryWrapper);
|
||||
patientHomeSearchParam.getStatusEnum(), patientHomeSearchParam.getPatientId(), searchKey,
|
||||
patientHomeSearchParam.getNursingLevelList(), queryWrapper);
|
||||
|
||||
patientHomeInfoPage.getRecords().forEach(e -> {
|
||||
// 护理级别
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 患者首页 应用实现
|
||||
@@ -36,7 +37,11 @@ public class PatientHomeController {
|
||||
public R<?> getPatientInfoInit(PatientHomeSearchParam patientHomeSearchParam,
|
||||
@RequestParam(value = "searchKey", defaultValue = "") String searchKey,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(value = "nursingLevelList", required = false) List<Integer> nursingLevelList,
|
||||
HttpServletRequest request) {
|
||||
// 将护理级别列表设置到查询参数中
|
||||
patientHomeSearchParam.setNursingLevelList(nursingLevelList);
|
||||
return patientHomeAppService.getPatientInfoInit(patientHomeSearchParam, searchKey, pageNo, pageSize, request);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.openhis.web.inpatientmanage.dto;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 患者首页查询参数
|
||||
*
|
||||
@@ -19,4 +21,7 @@ public class PatientHomeSearchParam {
|
||||
/** 患者ID */
|
||||
private Long patientId;
|
||||
|
||||
/** 护理级别列表(多选) */
|
||||
private List<Integer> nursingLevelList;
|
||||
|
||||
}
|
||||
|
||||
@@ -27,10 +27,13 @@ public interface PatientHomeAppMapper {
|
||||
* @param statusEnum 状态编码
|
||||
* @param patientId 患者ID
|
||||
* @param searchKey 查询条件
|
||||
* @param nursingLevelList 护理级别列表
|
||||
* @param queryWrapper 查询wrapper
|
||||
* @return 住院登记信息
|
||||
*/
|
||||
IPage<PatientHomeDto> getPage(@Param("page") Page<PatientHomeDto> page, @Param("statusEnum") Integer statusEnum,
|
||||
@Param("patientId") Long patientId, @Param("searchKey") String searchKey,
|
||||
@Param("nursingLevelList") List<Integer> nursingLevelList,
|
||||
@Param(Constants.WRAPPER) QueryWrapper<PatientHomeDto> queryWrapper);
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.openhis.web.lab.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.core.common.core.controller.BaseController;
|
||||
import com.core.common.core.domain.AjaxResult;
|
||||
import com.openhis.lab.domain.InspectionType;
|
||||
@@ -29,7 +30,25 @@ public class InspectionTypeController extends BaseController {
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
|
||||
/**
|
||||
* 获取检验类型列表
|
||||
* 分页获取检验类型列表
|
||||
*
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param searchKey 搜索关键词
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public AjaxResult getPage(
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "100") Integer pageSize,
|
||||
@RequestParam(value = "searchKey", required = false) String searchKey) {
|
||||
log.info("【检验类型】分页查询请求 - pageNo: {}, pageSize: {}, searchKey: {}", pageNo, pageSize, searchKey);
|
||||
IPage<InspectionType> result = inspectionTypeService.getPage(pageNo, pageSize, searchKey);
|
||||
log.info("【检验类型】分页查询完成 - 总记录数: {}, 当前页记录数: {}", result.getTotal(), result.getRecords().size());
|
||||
return AjaxResult.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取检验类型列表(不分页,兼容旧接口)
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list(InspectionType inspectionType) {
|
||||
|
||||
@@ -62,10 +62,10 @@ public class OutpatientInfusionAppServiceImpl implements IOutpatientInfusionAppS
|
||||
OutpatientStationInitDto initDto = new OutpatientStationInitDto();
|
||||
// 执行状态
|
||||
List<OutpatientStationInitDto.ServiceStatus> serviceStatusOptions = new ArrayList<>();
|
||||
serviceStatusOptions.add(new OutpatientStationInitDto.ServiceStatus(RequestStatus.ACTIVE.getValue(),
|
||||
"待执行"));
|
||||
serviceStatusOptions.add(new OutpatientStationInitDto.ServiceStatus(RequestStatus.COMPLETED.getValue(),
|
||||
RequestStatus.COMPLETED.getInfo()));
|
||||
// serviceStatusOptions.add(new OutpatientStationInitDto.ServiceStatus(RequestStatus.IN_PROGRESS.getValue(),
|
||||
// RequestStatus.IN_PROGRESS.getInfo()));
|
||||
serviceStatusOptions.add(new OutpatientStationInitDto.ServiceStatus(RequestStatus.CANCELLED.getValue(),
|
||||
RequestStatus.CANCELLED.getInfo()));
|
||||
initDto.setServiceStatusOptions(serviceStatusOptions);
|
||||
|
||||
@@ -199,13 +199,19 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
|
||||
// 此次chargeItem的就诊诊断id集合
|
||||
List<Long> diagIdList
|
||||
= chargeItemList.stream().map(ChargeItem::getEncounterDiagnosisId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
||||
if (diagIdList.isEmpty()) {
|
||||
throw new ServiceException("收费项的就诊诊断查询为空");
|
||||
}
|
||||
// 此次就诊的医疗类型列表
|
||||
List<EncounterDiagnosis> diagList = iEncounterDiagnosisService.getDiagnosisList(diagIdList);
|
||||
if (diagList.isEmpty()) {
|
||||
throw new ServiceException("就诊诊断查询为空,错误信息:EncounterDiagnosis");
|
||||
List<EncounterDiagnosis> diagList;
|
||||
if (diagIdList.isEmpty()) {
|
||||
// 收费项未关联就诊诊断(如挂号费、自动诊疗费等),则直接从就诊维度查询诊断
|
||||
diagList = iEncounterDiagnosisService.getDiagnosisList(prePaymentDto.getEncounterId());
|
||||
if (diagList.isEmpty()) {
|
||||
throw new ServiceException("当前就诊暂无诊断记录,请先由医生录入诊断后再进行收费");
|
||||
}
|
||||
} else {
|
||||
diagList = iEncounterDiagnosisService.getDiagnosisList(diagIdList);
|
||||
if (diagList.isEmpty()) {
|
||||
throw new ServiceException("就诊诊断查询为空");
|
||||
}
|
||||
}
|
||||
List<String> medTypeList
|
||||
= diagList.stream().map(EncounterDiagnosis::getMedTypeCode).distinct().collect(Collectors.toList());
|
||||
@@ -231,10 +237,20 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
|
||||
if (distinctAccountIdList.isEmpty()) {
|
||||
throw new ServiceException("未找到有效的账户信息");
|
||||
}
|
||||
// 只按账户ID查询,不再追加 encounter_id 条件
|
||||
// 原因:收费项上的 accountId 已能唯一定位账户,额外的 encounter_id 条件
|
||||
// 在挂号费等场景下可能因数据不一致导致查不到,引发误报
|
||||
List<Account> accountList = iAccountService.list(new LambdaQueryWrapper<Account>()
|
||||
.in(Account::getId, distinctAccountIdList).eq(Account::getEncounterId, prePaymentDto.getEncounterId()));
|
||||
.in(Account::getId, distinctAccountIdList));
|
||||
if (accountList.size() != distinctAccountIdList.size()) {
|
||||
throw new ServiceException("未查询到账户信息");
|
||||
// 部分账户查不到时,记录警告日志,并校验是否每个收费项都能找到对应账户
|
||||
Set<Long> foundAccountIds = accountList.stream().map(Account::getId).collect(Collectors.toSet());
|
||||
List<Long> missingAccountIds = distinctAccountIdList.stream()
|
||||
.filter(id -> !foundAccountIds.contains(id)).collect(Collectors.toList());
|
||||
if (accountList.isEmpty()) {
|
||||
throw new ServiceException("未查询到任何账户信息,encounterId:" + prePaymentDto.getEncounterId()
|
||||
+ ",期望accountId列表:" + distinctAccountIdList);
|
||||
}
|
||||
}
|
||||
|
||||
// 账户id,对应的账单列表
|
||||
@@ -622,6 +638,37 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
|
||||
});
|
||||
|
||||
if (!medicationRequestIdList.isEmpty()) {
|
||||
// 获取药品请求信息,为输液类药品生成服务请求
|
||||
List<MedicationRequest> medicationRequests = medicationRequestService.listByIds(medicationRequestIdList);
|
||||
|
||||
// 为输液类药品生成 wor_service_request 记录
|
||||
for (MedicationRequest medReq : medicationRequests) {
|
||||
if (medReq.getInfusionFlag() != null && medReq.getInfusionFlag() == 1) {
|
||||
ServiceRequest serviceRequest = new ServiceRequest();
|
||||
serviceRequest.setBasedOnId(medReq.getId())
|
||||
.setBasedOnTable(CommonConstants.TableName.MED_MEDICATION_REQUEST)
|
||||
.setEncounterId(medReq.getEncounterId())
|
||||
.setPatientId(medReq.getPatientId())
|
||||
.setActivityId(medReq.getMedicationId())
|
||||
.setStatusEnum(RequestStatus.ACTIVE.getValue()) // 状态设为已发送 (2),这样门诊输液页面才能查到
|
||||
.setGroupId(medReq.getGroupId())
|
||||
.setOrgId(medReq.getOrgId())
|
||||
.setRequesterId(medReq.getPractitionerId())
|
||||
.setAuthoredTime(new Date())
|
||||
.setEncounterDiagnosisId(medReq.getEncounterDiagnosisId())
|
||||
.setConditionId(medReq.getConditionId())
|
||||
.setQuantity(medReq.getQuantity())
|
||||
.setUnitCode(medReq.getUnitCode())
|
||||
.setPriorityEnum(medReq.getPriorityEnum())
|
||||
.setPerformFlag(Whether.NO.getValue())
|
||||
.setIntentEnum(medReq.getIntentEnum())
|
||||
.setCategoryEnum(medReq.getCategoryEnum())
|
||||
.setYbClassEnum(medReq.getYbClassEnum())
|
||||
.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.SERVICE_RES_NO.getPrefix(), 4));
|
||||
serviceRequestService.save(serviceRequest);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新请求状态为已完成
|
||||
medicationRequestService.updateCompletedStatusBatch(medicationRequestIdList, null, null);
|
||||
// 更新药品发放状态为待配药
|
||||
@@ -2125,14 +2172,18 @@ public class PaymentRecServiceImpl implements IPaymentRecService {
|
||||
piModel.setBusNo(chargeItem.getBusNo());
|
||||
|
||||
EncounterDiagnosis encounterDiagnosis;
|
||||
Optional<EncounterDiagnosis> optional
|
||||
= diagList.stream().filter(e -> e.getId().equals(chargeItem.getEncounterDiagnosisId())).findFirst();
|
||||
|
||||
if (optional.isPresent()) {
|
||||
encounterDiagnosis = optional.get();
|
||||
if (chargeItem.getEncounterDiagnosisId() == null) {
|
||||
// 收费项未关联就诊诊断(如挂号费、自动诊疗费等),取诊断列表第一条作为兜底
|
||||
encounterDiagnosis = diagList.get(0);
|
||||
} else {
|
||||
throw new ServiceException(
|
||||
"诊断信息与收费项的诊断信息未对应,错误信息:费用项" + chargeItem.getBusNo() + chargeItem.getEncounterDiagnosisId());
|
||||
Optional<EncounterDiagnosis> optional
|
||||
= diagList.stream().filter(e -> e.getId().equals(chargeItem.getEncounterDiagnosisId())).findFirst();
|
||||
if (optional.isPresent()) {
|
||||
encounterDiagnosis = optional.get();
|
||||
} else {
|
||||
// 收费项关联的诊断ID在diagList中找不到,也取第一条兜底
|
||||
encounterDiagnosis = diagList.get(0);
|
||||
}
|
||||
}
|
||||
piModel.setMedType(encounterDiagnosis.getMedTypeCode());
|
||||
piModel.setTotalPrice(chargeItem.getTotalPrice());
|
||||
|
||||
@@ -236,6 +236,11 @@ public class WesternMedicineDispenseAppServiceImpl implements IWesternMedicineDi
|
||||
EnumUtils.getInfoByValue(DispenseStatus.class, medicineDispenseOrder.getStatusEnum()));
|
||||
// 设置所在表名
|
||||
medicineDispenseOrder.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION);
|
||||
// 处方类型(发药类型:门诊/住院等)
|
||||
if (medicineDispenseOrder.getDispenseEnum() != null) {
|
||||
medicineDispenseOrder.setDispenseEnum_enumText(
|
||||
EnumUtils.getInfoByValue(EncounterClass.class, medicineDispenseOrder.getDispenseEnum()));
|
||||
}
|
||||
});
|
||||
return R.ok(medicineDispenseOrderPage);
|
||||
}
|
||||
|
||||
@@ -271,6 +271,12 @@ public class ItemDispenseOrderDto {
|
||||
private String medTypeCode;
|
||||
private String medTypeCode_dictText;
|
||||
|
||||
/**
|
||||
* 发药类型(处方类型:门诊/住院等)
|
||||
*/
|
||||
private Integer dispenseEnum;
|
||||
private String dispenseEnum_enumText;
|
||||
|
||||
/**
|
||||
* 输液标志
|
||||
*/
|
||||
|
||||
@@ -29,9 +29,12 @@ import com.openhis.web.regdoctorstation.appservice.IAdviceManageAppService;
|
||||
import com.openhis.web.regdoctorstation.dto.*;
|
||||
import com.openhis.web.regdoctorstation.mapper.AdviceManageAppMapper;
|
||||
import com.openhis.web.regdoctorstation.utils.RegPrescriptionUtils;
|
||||
import com.openhis.workflow.domain.ActivityDefinition;
|
||||
import com.openhis.workflow.domain.DeviceRequest;
|
||||
import com.openhis.workflow.domain.ServiceRequest;
|
||||
import com.openhis.workflow.service.IActivityDefinitionService;
|
||||
import com.openhis.workflow.domain.ActivityDefinition;
|
||||
import com.openhis.workflow.service.IDeviceDispenseService;
|
||||
import com.openhis.workflow.service.IDeviceRequestService;
|
||||
import com.openhis.workflow.service.IServiceRequestService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -76,6 +79,12 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
||||
@Resource
|
||||
IActivityDefinitionService iActivityDefinitionService;
|
||||
|
||||
@Resource
|
||||
IDeviceRequestService iDeviceRequestService;
|
||||
|
||||
@Resource
|
||||
IDeviceDispenseService iDeviceDispenseService;
|
||||
|
||||
/**
|
||||
* 查询住院患者信息
|
||||
*
|
||||
@@ -167,12 +176,16 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
||||
Long organizationId = regAdviceSaveParam.getOrganizationId();
|
||||
// 医嘱分类信息
|
||||
List<RegAdviceSaveDto> regAdviceSaveList = regAdviceSaveParam.getRegAdviceSaveList();
|
||||
|
||||
// 药品
|
||||
List<RegAdviceSaveDto> medicineList = regAdviceSaveList.stream()
|
||||
.filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())).collect(Collectors.toList());
|
||||
// 诊疗活动
|
||||
List<RegAdviceSaveDto> activityList = regAdviceSaveList.stream()
|
||||
.filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())).collect(Collectors.toList());
|
||||
// 耗材 🔧 Bug #147 修复
|
||||
List<RegAdviceSaveDto> deviceList = regAdviceSaveList.stream()
|
||||
.filter(e -> ItemType.DEVICE.getValue().equals(e.getAdviceType())).collect(Collectors.toList());
|
||||
|
||||
// 保存时,校验临时医嘱库存
|
||||
if (AdviceOpType.SAVE_ADVICE.getCode().equals(adviceOpType)) {
|
||||
@@ -209,6 +222,11 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
||||
*/
|
||||
this.handService(activityList, startTime, authoredTime, curDate, adviceOpType, organizationId, signCode);
|
||||
|
||||
/**
|
||||
* 🔧 Bug #147 修复:处理耗材请求
|
||||
*/
|
||||
this.handDevice(deviceList, startTime, authoredTime, curDate, adviceOpType, organizationId, signCode);
|
||||
|
||||
// 签发时,把草稿状态的账单更新为待收费
|
||||
if (AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType) && !regAdviceSaveList.isEmpty()) {
|
||||
// 签发的医嘱id集合
|
||||
@@ -593,6 +611,150 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 🔧 Bug #147 修复:处理耗材
|
||||
*/
|
||||
private void handDevice(List<RegAdviceSaveDto> deviceList, Date startTime, Date authoredTime, Date curDate,
|
||||
String adviceOpType, Long organizationId, String signCode) {
|
||||
// 当前登录账号的科室id
|
||||
Long orgId = SecurityUtils.getLoginUser().getOrgId();
|
||||
// 获取当前登录用户的tenantId
|
||||
Integer tenantId = SecurityUtils.getLoginUser().getTenantId();
|
||||
// 保存操作
|
||||
boolean is_save = AdviceOpType.SAVE_ADVICE.getCode().equals(adviceOpType);
|
||||
// 签发操作
|
||||
boolean is_sign = AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType);
|
||||
|
||||
// 删除
|
||||
List<RegAdviceSaveDto> deleteList = deviceList.stream()
|
||||
.filter(e -> DbOpType.DELETE.getCode().equals(e.getDbOpType())).collect(Collectors.toList());
|
||||
for (RegAdviceSaveDto regAdviceSaveDto : deleteList) {
|
||||
iDeviceRequestService.removeById(regAdviceSaveDto.getRequestId());
|
||||
// 删除已经产生的耗材发放信息
|
||||
iDeviceDispenseService.deleteDeviceDispense(regAdviceSaveDto.getRequestId());
|
||||
// 删除费用项
|
||||
iChargeItemService.deleteByServiceTableAndId(CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
||||
regAdviceSaveDto.getRequestId());
|
||||
}
|
||||
|
||||
// 声明耗材请求
|
||||
DeviceRequest deviceRequest;
|
||||
// 声明费用项
|
||||
ChargeItem chargeItem;
|
||||
|
||||
// 新增 + 修改 (长期医嘱)
|
||||
List<RegAdviceSaveDto> longInsertOrUpdateList = deviceList.stream().filter(e -> TherapyTimeType.LONG_TERM
|
||||
.getValue().equals(e.getTherapyEnum())
|
||||
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (RegAdviceSaveDto regAdviceSaveDto : longInsertOrUpdateList) {
|
||||
deviceRequest = new DeviceRequest();
|
||||
deviceRequest.setId(regAdviceSaveDto.getRequestId()); // 主键id
|
||||
deviceRequest.setStatusEnum(is_save ? RequestStatus.DRAFT.getValue() : RequestStatus.ACTIVE.getValue()); // 请求状态
|
||||
deviceRequest.setTenantId(SecurityUtils.getLoginUser().getTenantId()); // 显式设置租户ID
|
||||
if (is_sign) {
|
||||
deviceRequest.setReqAuthoredTime(authoredTime); // 医嘱签发时间
|
||||
}
|
||||
// 保存时处理的字段属性
|
||||
if (is_save) {
|
||||
deviceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.DEVICE_RES_NO.getPrefix(), 4));
|
||||
deviceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
|
||||
deviceRequest.setQuantity(regAdviceSaveDto.getQuantity()); // 请求数量
|
||||
deviceRequest.setUnitCode(regAdviceSaveDto.getUnitCode()); // 请求单位编码
|
||||
deviceRequest.setLotNumber(regAdviceSaveDto.getLotNumber()); // 产品批号
|
||||
deviceRequest.setCategoryEnum(regAdviceSaveDto.getCategoryEnum()); // 请求类型
|
||||
deviceRequest.setDeviceDefId(regAdviceSaveDto.getAdviceDefinitionId());// 耗材定义id
|
||||
deviceRequest.setPatientId(regAdviceSaveDto.getPatientId()); // 患者
|
||||
deviceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
|
||||
deviceRequest.setOrgId(regAdviceSaveDto.getFounderOrgId()); // 开方人科室
|
||||
deviceRequest.setReqAuthoredTime(startTime); // 医嘱开始时间
|
||||
deviceRequest.setPerformLocation(regAdviceSaveDto.getLocationId()); // 发放科室
|
||||
deviceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
|
||||
deviceRequest.setPackageId(regAdviceSaveDto.getPackageId()); // 组套id
|
||||
deviceRequest.setContentJson(regAdviceSaveDto.getContentJson()); // 请求内容json
|
||||
deviceRequest.setYbClassEnum(regAdviceSaveDto.getYbClassEnum());// 类别医保编码
|
||||
deviceRequest.setConditionId(regAdviceSaveDto.getConditionId()); // 诊断id
|
||||
deviceRequest.setEncounterDiagnosisId(regAdviceSaveDto.getEncounterDiagnosisId()); // 就诊诊断id
|
||||
}
|
||||
iDeviceRequestService.saveOrUpdate(deviceRequest);
|
||||
}
|
||||
|
||||
// 新增 + 修改 (临时医嘱)
|
||||
List<RegAdviceSaveDto> tempInsertOrUpdateList = deviceList.stream().filter(e -> TherapyTimeType.TEMPORARY
|
||||
.getValue().equals(e.getTherapyEnum())
|
||||
&& (DbOpType.INSERT.getCode().equals(e.getDbOpType()) || DbOpType.UPDATE.getCode().equals(e.getDbOpType())))
|
||||
.collect(Collectors.toList());
|
||||
for (RegAdviceSaveDto regAdviceSaveDto : tempInsertOrUpdateList) {
|
||||
deviceRequest = new DeviceRequest();
|
||||
deviceRequest.setId(regAdviceSaveDto.getRequestId()); // 主键id
|
||||
deviceRequest.setStatusEnum(is_save ? RequestStatus.DRAFT.getValue() : RequestStatus.ACTIVE.getValue()); // 请求状态
|
||||
deviceRequest.setTenantId(SecurityUtils.getLoginUser().getTenantId()); // 显式设置租户ID
|
||||
if (is_sign) {
|
||||
deviceRequest.setReqAuthoredTime(authoredTime); // 医嘱签发时间
|
||||
}
|
||||
// 保存时处理的字段属性
|
||||
if (is_save) {
|
||||
deviceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.DEVICE_RES_NO.getPrefix(), 4));
|
||||
deviceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
|
||||
deviceRequest.setQuantity(regAdviceSaveDto.getQuantity()); // 请求数量
|
||||
deviceRequest.setUnitCode(regAdviceSaveDto.getUnitCode()); // 请求单位编码
|
||||
deviceRequest.setLotNumber(regAdviceSaveDto.getLotNumber()); // 产品批号
|
||||
deviceRequest.setCategoryEnum(regAdviceSaveDto.getCategoryEnum()); // 请求类型
|
||||
deviceRequest.setDeviceDefId(regAdviceSaveDto.getAdviceDefinitionId());// 耗材定义id
|
||||
deviceRequest.setPatientId(regAdviceSaveDto.getPatientId()); // 患者
|
||||
deviceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
|
||||
deviceRequest.setOrgId(regAdviceSaveDto.getFounderOrgId()); // 开方人科室
|
||||
deviceRequest.setReqAuthoredTime(startTime); // 医嘱开始时间
|
||||
deviceRequest.setPerformLocation(regAdviceSaveDto.getLocationId()); // 发放科室
|
||||
deviceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
|
||||
deviceRequest.setPackageId(regAdviceSaveDto.getPackageId()); // 组套id
|
||||
deviceRequest.setContentJson(regAdviceSaveDto.getContentJson()); // 请求内容json
|
||||
deviceRequest.setYbClassEnum(regAdviceSaveDto.getYbClassEnum());// 类别医保编码
|
||||
deviceRequest.setConditionId(regAdviceSaveDto.getConditionId()); // 诊断id
|
||||
deviceRequest.setEncounterDiagnosisId(regAdviceSaveDto.getEncounterDiagnosisId()); // 就诊诊断id
|
||||
}
|
||||
iDeviceRequestService.saveOrUpdate(deviceRequest);
|
||||
|
||||
// 保存时,保存耗材费用项
|
||||
if (is_save) {
|
||||
// 处理耗材发放
|
||||
Long dispenseId = iDeviceDispenseService.handleDeviceDispense(deviceRequest,
|
||||
regAdviceSaveDto.getDbOpType());
|
||||
|
||||
// 保存耗材费用项
|
||||
chargeItem = new ChargeItem();
|
||||
chargeItem.setId(regAdviceSaveDto.getChargeItemId()); // 费用项id
|
||||
chargeItem.setStatusEnum(ChargeItemStatus.DRAFT.getValue()); // 收费状态
|
||||
chargeItem.setBusNo(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix().concat(deviceRequest.getBusNo()));
|
||||
chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
|
||||
chargeItem.setPatientId(regAdviceSaveDto.getPatientId()); // 患者
|
||||
chargeItem.setContextEnum(regAdviceSaveDto.getAdviceType()); // 类型
|
||||
chargeItem.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
|
||||
chargeItem.setDefinitionId(regAdviceSaveDto.getDefinitionId()); // 费用定价ID
|
||||
chargeItem.setDefDetailId(regAdviceSaveDto.getDefinitionDetailId()); // 定价子表主键
|
||||
chargeItem.setEntererId(regAdviceSaveDto.getPractitionerId());// 开立人ID
|
||||
chargeItem.setEnteredDate(curDate); // 开立时间
|
||||
chargeItem.setServiceTable(CommonConstants.TableName.WOR_DEVICE_REQUEST);// 医疗服务类型
|
||||
chargeItem.setServiceId(deviceRequest.getId()); // 医疗服务ID
|
||||
chargeItem.setProductTable(regAdviceSaveDto.getAdviceTableName());// 产品所在表
|
||||
chargeItem.setProductId(regAdviceSaveDto.getAdviceDefinitionId());// 收费项id
|
||||
chargeItem.setAccountId(regAdviceSaveDto.getAccountId());// 关联账户ID
|
||||
chargeItem.setRequestingOrgId(orgId); // 开立科室
|
||||
chargeItem.setConditionId(regAdviceSaveDto.getConditionId()); // 诊断id
|
||||
chargeItem.setEncounterDiagnosisId(regAdviceSaveDto.getEncounterDiagnosisId()); // 就诊诊断id
|
||||
chargeItem.setDispenseId(dispenseId); // 发放ID
|
||||
|
||||
chargeItem.setQuantityValue(regAdviceSaveDto.getQuantity()); // 数量
|
||||
chargeItem.setQuantityUnit(regAdviceSaveDto.getUnitCode()); // 单位
|
||||
chargeItem.setUnitPrice(regAdviceSaveDto.getUnitPrice()); // 单价
|
||||
chargeItem.setTotalPrice(regAdviceSaveDto.getTotalPrice()); // 总价
|
||||
|
||||
iChargeItemService.saveOrUpdate(chargeItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询住院医嘱请求数据
|
||||
*
|
||||
|
||||
@@ -30,16 +30,22 @@
|
||||
T1.pricing_flag,
|
||||
T1.sort_order,
|
||||
T1.service_range,
|
||||
T1.inspection_type_id,
|
||||
T2.type_code as item_type_code,
|
||||
T2.yb_type,
|
||||
T2.price_code,
|
||||
T2.price as retail_price,
|
||||
T4.amount as maximum_retail_price
|
||||
T4.amount as maximum_retail_price,
|
||||
T3.name as test_type
|
||||
FROM wor_activity_definition T1
|
||||
/* 只JOIN必要的价格表,使用INNER JOIN避免笛卡尔积 */
|
||||
INNER JOIN adm_charge_item_definition T2
|
||||
ON T1.id = T2.instance_id
|
||||
AND T2.instance_table = 'wor_activity_definition'
|
||||
/* 检验类型关联 */
|
||||
LEFT JOIN inspection_type T3
|
||||
ON T1.inspection_type_id = T3.id
|
||||
AND T3.valid_flag = 1
|
||||
/* 最高零售价使用LEFT JOIN,因为可能不存在 */
|
||||
LEFT JOIN adm_charge_item_def_detail T4
|
||||
ON T4.definition_id = T2.id
|
||||
@@ -49,10 +55,10 @@
|
||||
<if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
|
||||
<choose>
|
||||
<when test="ew.customSqlSegment.contains('tenant_id')">
|
||||
${ew.customSqlSegment.replaceFirst('tenant_id', 'T1.tenant_id').replaceFirst('status_enum', 'T1.status_enum').replaceFirst('WHERE', 'AND')}
|
||||
${ew.customSqlSegment.replaceFirst('tenant_id', 'T1.tenant_id').replaceFirst('status_enum', 'T1.status_enum').replaceFirst('name', 'T1.name').replaceFirst('WHERE', 'AND')}
|
||||
</when>
|
||||
<otherwise>
|
||||
${ew.customSqlSegment.replaceFirst('status_enum', 'T1.status_enum').replaceFirst('WHERE', 'AND')}
|
||||
${ew.customSqlSegment.replaceFirst('status_enum', 'T1.status_enum').replaceFirst('name', 'T1.name').replaceFirst('WHERE', 'AND')}
|
||||
</otherwise>
|
||||
</choose>
|
||||
</if>
|
||||
@@ -97,9 +103,13 @@
|
||||
T1.children_json,
|
||||
T1.pricing_flag,
|
||||
T1.sort_order,
|
||||
T1.service_range
|
||||
T1.service_range,
|
||||
T1.inspection_type_id,
|
||||
T3.name as test_type
|
||||
FROM wor_activity_definition T1
|
||||
LEFT JOIN adm_charge_item_definition T2 ON T1.id = T2.instance_id
|
||||
/* 检验类型关联 */
|
||||
LEFT JOIN inspection_type T3 ON T1.inspection_type_id = T3.id AND T3.valid_flag = 1
|
||||
<where>
|
||||
T1.delete_flag = '0'
|
||||
AND T2.instance_table = 'wor_activity_definition'
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
(SELECT
|
||||
DISTINCT ON (T1.ID)
|
||||
T1.tenant_id,
|
||||
2 AS advice_type,
|
||||
4 AS advice_type,
|
||||
T1.bus_no AS bus_no,
|
||||
T1.category_code AS category_code,
|
||||
'' AS pharmacology_category_code,
|
||||
@@ -204,8 +204,16 @@
|
||||
T1.yb_no AS yb_no,
|
||||
'' AS product_name,
|
||||
-- 前端"类型"列:显示目录类别(category_code)
|
||||
-- 将category_code转换为整数,用于字典转换(字典转换框架会自动填充activityType_dictText)
|
||||
CAST(T1.category_code AS INTEGER) AS activity_type,
|
||||
-- 🔧 Bug #177 修复:将category_code(中文)转换为对应的整数值,用于字典转换
|
||||
-- 检验->1, 检查->2, 护理->3, 手术->4, 其他->5
|
||||
CASE T1.category_code
|
||||
WHEN '检验' THEN 1
|
||||
WHEN '检查' THEN 2
|
||||
WHEN '护理' THEN 3
|
||||
WHEN '手术' THEN 4
|
||||
WHEN '其他' THEN 5
|
||||
ELSE 0
|
||||
END AS activity_type,
|
||||
NULL AS activity_type_dictText,
|
||||
-- 前端"包装单位"列:显示使用单位(permitted_unit_code)
|
||||
T1.permitted_unit_code AS unit_code,
|
||||
@@ -675,4 +683,13 @@
|
||||
AND wad.ID = wsr.activity_id )
|
||||
</select>
|
||||
|
||||
<!-- 获取就诊的默认账户ID -->
|
||||
<select id="getDefaultAccountId" resultType="java.lang.Long">
|
||||
SELECT aa.id
|
||||
FROM adm_account aa
|
||||
WHERE aa.delete_flag = '0'
|
||||
AND aa.encounter_id = #{encounterId}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -131,7 +131,9 @@
|
||||
T1.med_type_code,
|
||||
T1.diagnosis_desc,
|
||||
T2.verification_status_enum,
|
||||
T2.yb_no
|
||||
T2.yb_no,
|
||||
T1.onset_date AS onsetDate,
|
||||
T1.diagnosis_time AS diagnosisTime
|
||||
FROM adm_encounter_diagnosis AS T1
|
||||
LEFT JOIN cli_condition AS T2 ON T2.ID = T1.condition_id
|
||||
AND T2.delete_flag = '0' AND T2.tcm_flag = 0
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
AND ddo.delete_flag = '0'
|
||||
|
||||
WHERE dd.delete_flag = '0'
|
||||
AND dd.is_valid = 0
|
||||
|
||||
<!-- 关键:医院 + 科室联合可见 -->
|
||||
<if test="organizationId != null and organizationId != 0">
|
||||
@@ -80,6 +81,10 @@
|
||||
AND dd.name LIKE CONCAT('%', #{name}, '%')
|
||||
</if>
|
||||
|
||||
<if test="primaryMenuEnum != null">
|
||||
AND dd.primary_menu_enum = #{primaryMenuEnum}
|
||||
</if>
|
||||
|
||||
GROUP BY dd.id, dd.primary_menu_enum, dd.sub_menu
|
||||
ORDER BY dd.display_order
|
||||
|
||||
|
||||
@@ -289,49 +289,49 @@
|
||||
LIMIT 1
|
||||
) AS ward ON ward.encounter_id = ae.id
|
||||
LEFT JOIN (
|
||||
SELECT aep.encounter_id,
|
||||
pra.id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code = #{primaryNurse}
|
||||
LIMIT 1
|
||||
) AS primaryNurse ON primaryNurse.encounter_id = ae.id
|
||||
SELECT aep.encounter_id,
|
||||
aep.practitioner_id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code::text = CAST(#{primaryNurse} AS TEXT)
|
||||
LIMIT 1
|
||||
) AS primaryNurse ON primaryNurse.encounter_id = ae.id
|
||||
LEFT JOIN (
|
||||
SELECT aep.encounter_id,
|
||||
pra.id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code = #{attendingDoctor}
|
||||
LIMIT 1
|
||||
) AS attendingDoctor ON attendingDoctor.encounter_id = ae.id
|
||||
SELECT aep.encounter_id,
|
||||
aep.practitioner_id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code::text = CAST(#{attendingDoctor} AS TEXT)
|
||||
LIMIT 1
|
||||
) AS attendingDoctor ON attendingDoctor.encounter_id = ae.id
|
||||
LEFT JOIN (
|
||||
SELECT aep.encounter_id,
|
||||
pra.id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code = #{admittingDoctor}
|
||||
LIMIT 1
|
||||
) AS admittingDoctor ON admittingDoctor.encounter_id = ae.id
|
||||
SELECT aep.encounter_id,
|
||||
aep.practitioner_id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code::text = CAST(#{admittingDoctor} AS TEXT)
|
||||
LIMIT 1
|
||||
) AS admittingDoctor ON admittingDoctor.encounter_id = ae.id
|
||||
LEFT JOIN (
|
||||
SELECT aep.encounter_id,
|
||||
pra.id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code = #{chiefDoctor}
|
||||
LIMIT 1
|
||||
) AS chiefDoctor ON chiefDoctor.encounter_id = ae.id
|
||||
SELECT aep.encounter_id,
|
||||
aep.practitioner_id AS practitioner_id,
|
||||
pra."name" AS practitioner_name
|
||||
FROM adm_encounter_participant aep
|
||||
LEFT JOIN adm_practitioner pra ON aep.practitioner_id = pra.id AND pra.delete_flag = '0'
|
||||
WHERE aep.status_enum = #{active}
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.type_code::text = CAST(#{chiefDoctor} AS TEXT)
|
||||
LIMIT 1
|
||||
) AS chiefDoctor ON chiefDoctor.encounter_id = ae.id
|
||||
LEFT JOIN adm_organization ao
|
||||
ON ao.id = ae.organization_id
|
||||
AND ao.delete_flag = '0'
|
||||
@@ -575,7 +575,7 @@
|
||||
ON ae.id = aep.encounter_id
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.status_enum = #{active}
|
||||
AND aep.type_code = #{admittingDoctor}
|
||||
AND aep.type_code::text = #{admittingDoctor}::text
|
||||
LEFT JOIN adm_practitioner pra
|
||||
ON aep.practitioner_id = pra.id
|
||||
AND pra.delete_flag = '0'
|
||||
@@ -709,7 +709,7 @@
|
||||
ON ae.id = aep.encounter_id
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.status_enum = #{active}
|
||||
AND aep.type_code = #{admittingDoctor}
|
||||
AND aep.type_code::text = #{admittingDoctor}::text
|
||||
LEFT JOIN adm_practitioner pra
|
||||
ON aep.practitioner_id = pra.id
|
||||
AND pra.delete_flag = '0'
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
T5.ward_location_id,
|
||||
T5.bed_location_id
|
||||
FROM (SELECT T1.tenant_id,
|
||||
T1.id AS patient_id, --患者ID
|
||||
T1.name AS patient_name, --患者姓名
|
||||
T1.bus_no AS patient_bus_no, --病历号
|
||||
T1.birth_date, --患者出生日期
|
||||
T1.gender_enum, --患者性别
|
||||
T1.organization_id AS org_id, --科室ID
|
||||
T2.id AS encounter_id, --就诊ID
|
||||
T1.id AS patient_id, --患者ID
|
||||
T1.name AS patient_name, --患者姓名
|
||||
T1.bus_no AS patient_bus_no, --病历号
|
||||
T1.birth_date, --患者出生日期
|
||||
T1.gender_enum, --患者性别
|
||||
T2.organization_id AS org_id, --科室ID(从就诊表取)
|
||||
T2.id AS encounter_id, --就诊ID
|
||||
T2.start_time AS admissionDate, --入院日期
|
||||
T3.location_id AS ward_location_id, --病区
|
||||
T4.location_id AS bed_location_id --床号
|
||||
@@ -31,33 +31,33 @@
|
||||
ON T2.patient_id = T1.id
|
||||
AND T2.class_enum = #{classEnum}
|
||||
AND T2.delete_flag = '0'
|
||||
INNER JOIN (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag
|
||||
FROM (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag,
|
||||
ROW_NUMBER() OVER (PARTITION BY encounter_id
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN update_time IS NULL THEN create_time
|
||||
ELSE update_time
|
||||
END DESC) AS rn
|
||||
FROM adm_encounter_location
|
||||
WHERE form_enum = #{ward}
|
||||
AND delete_flag = '0'
|
||||
) ranked
|
||||
WHERE rn = 1) AS T3
|
||||
ON T3.encounter_id = T2.ID
|
||||
INNER JOIN adm_encounter_location AS T4
|
||||
INNER JOIN (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag
|
||||
FROM (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag,
|
||||
ROW_NUMBER() OVER (PARTITION BY encounter_id
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN update_time IS NULL THEN create_time
|
||||
ELSE update_time
|
||||
END DESC) AS rn
|
||||
FROM adm_encounter_location
|
||||
WHERE form_enum = #{ward}
|
||||
AND delete_flag = '0'
|
||||
) ranked
|
||||
WHERE rn = 1) AS T3
|
||||
ON T3.encounter_id = T2.ID
|
||||
LEFT JOIN adm_encounter_location AS T4
|
||||
ON T4.encounter_id = T2.ID
|
||||
AND T4.form_enum = #{bed}
|
||||
AND T4.status_enum = #{active}
|
||||
AND T4.delete_flag = '0'
|
||||
WHERE T1.delete_flag = '0'
|
||||
ORDER BY T4.location_id ASC) AS T5
|
||||
WHERE T1.delete_flag = '0'
|
||||
ORDER BY T4.location_id ASC) AS T5
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
@@ -79,12 +79,12 @@
|
||||
T6.context_json,
|
||||
T6.bed_location_id
|
||||
FROM (SELECT T1.tenant_id,
|
||||
T1.id AS patient_id, --患者ID
|
||||
T1.name AS patient_name, --患者姓名
|
||||
T1.birth_date, --患者出生日期
|
||||
T1.gender_enum, --患者性别
|
||||
T1.organization_id AS org_id, --科室ID
|
||||
T2.id AS encounter_id, --就诊ID
|
||||
T1.id AS patient_id, --患者ID
|
||||
T1.name AS patient_name, --患者姓名
|
||||
T1.birth_date, --患者出生日期
|
||||
T1.gender_enum, --患者性别
|
||||
T2.organization_id AS org_id, --科室ID(从就诊表取)
|
||||
T2.id AS encounter_id, --就诊ID
|
||||
T2.start_time AS admissionDate, --入院日期
|
||||
T3.location_id AS ward_location_id, --病区
|
||||
T5.id AS record_id, --记录单ID
|
||||
@@ -97,32 +97,32 @@
|
||||
ON T2.patient_id = T1.id
|
||||
AND T2.class_enum = #{classEnum}
|
||||
AND T2.delete_flag = '0'
|
||||
INNER JOIN (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag
|
||||
FROM (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag,
|
||||
ROW_NUMBER() OVER (PARTITION BY encounter_id
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN update_time IS NULL THEN create_time
|
||||
ELSE update_time
|
||||
END DESC) AS rn
|
||||
FROM adm_encounter_location
|
||||
WHERE form_enum = #{ward}
|
||||
AND delete_flag = '0'
|
||||
) ranked
|
||||
WHERE rn = 1) AS T3
|
||||
ON T3.encounter_id = T2.ID
|
||||
INNER JOIN adm_encounter_location AS T4
|
||||
INNER JOIN (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag
|
||||
FROM (SELECT encounter_id,
|
||||
location_id,
|
||||
form_enum,
|
||||
delete_flag,
|
||||
ROW_NUMBER() OVER (PARTITION BY encounter_id
|
||||
ORDER BY
|
||||
CASE
|
||||
WHEN update_time IS NULL THEN create_time
|
||||
ELSE update_time
|
||||
END DESC) AS rn
|
||||
FROM adm_encounter_location
|
||||
WHERE form_enum = #{ward}
|
||||
AND delete_flag = '0'
|
||||
) ranked
|
||||
WHERE rn = 1) AS T3
|
||||
ON T3.encounter_id = T2.ID
|
||||
LEFT JOIN adm_encounter_location AS T4
|
||||
ON T4.encounter_id = T2.ID
|
||||
AND T4.form_enum = #{bed}
|
||||
AND T4.status_enum = #{active}
|
||||
AND T4.delete_flag = '0'
|
||||
LEFT JOIN doc_emr AS T5
|
||||
LEFT JOIN doc_emr AS T5
|
||||
ON T5.patient_id = T1.id
|
||||
AND T5.encounter_id = T2.ID
|
||||
AND T5.class_enum = 1 --护理记录单
|
||||
|
||||
@@ -242,6 +242,14 @@
|
||||
)
|
||||
)
|
||||
</if>
|
||||
|
||||
-- 护理级别筛选(多选)
|
||||
<if test="nursingLevelList != null and nursingLevelList.size() > 0">
|
||||
AND T2.priority_enum IN
|
||||
<foreach collection="nursingLevelList" item="level" open="(" separator="," close=")">
|
||||
#{level}
|
||||
</foreach>
|
||||
</if>
|
||||
) patient_base
|
||||
) ranked_result
|
||||
WHERE rn = 1
|
||||
|
||||
@@ -34,14 +34,16 @@
|
||||
ON e.id = sr.encounter_id
|
||||
AND sr.refund_service_id IS NULL
|
||||
AND sr.delete_flag = '0'
|
||||
INNER JOIN med_medication_request mmr
|
||||
ON mmr.id = sr.based_on_id
|
||||
AND mmr.delete_flag = '0'
|
||||
AND mmr.infusion_flag = 1
|
||||
LEFT JOIN adm_patient pt
|
||||
ON pt.id = sr.patient_id
|
||||
AND pt.delete_flag = '0'
|
||||
LEFT JOIN wor_activity_definition ad
|
||||
ON ad.id = sr.activity_id
|
||||
AND ad.delete_flag = '0'
|
||||
WHERE e.delete_flag = '0'
|
||||
AND sr.status_enum IN (#{inProgress}, #{completed}, #{cancelled})
|
||||
AND sr.based_on_table = #{medMedicationRequest}
|
||||
GROUP BY sr.status_enum,
|
||||
sr.encounter_id,
|
||||
e.bus_no,
|
||||
@@ -106,7 +108,7 @@
|
||||
mmr.performer_id,
|
||||
dis.status_enum AS dispense_status,
|
||||
mmd."name" AS medication_name,
|
||||
ad."name" AS service_name,
|
||||
mmd."name" AS service_name,
|
||||
ap."name" AS practitioner_name,
|
||||
o."name" AS dept_name,
|
||||
-- 新增子查询:查询配药人
|
||||
@@ -128,15 +130,12 @@
|
||||
AND wsr.delete_flag = '0'
|
||||
AND wsr.refund_service_id IS NULL
|
||||
LEFT JOIN med_medication_request mmr
|
||||
ON mmr.group_id = wsr.group_id
|
||||
ON mmr.id = wsr.based_on_id
|
||||
AND mmr.delete_flag = '0'
|
||||
AND mmr.infusion_flag = 1
|
||||
LEFT JOIN med_medication_dispense dis
|
||||
ON dis.med_req_id = mmr.id
|
||||
AND dis.delete_flag = '0'
|
||||
LEFT JOIN wor_activity_definition ad
|
||||
ON ad.id = wsr.activity_id
|
||||
AND ad.delete_flag = '0'
|
||||
LEFT JOIN med_medication_definition mmd
|
||||
ON mmr.medication_id = mmd.id
|
||||
AND mmd.delete_flag = '0'
|
||||
@@ -147,7 +146,6 @@
|
||||
ON o.id = wsr.org_id
|
||||
AND o.delete_flag = '0'
|
||||
WHERE ae.id = #{encounterId}
|
||||
AND ad.category_code = '21'
|
||||
AND wsr.based_on_table = #{medMedicationRequest}
|
||||
AND ae.delete_flag = '0') AS pr
|
||||
${ew.customSqlSegment}
|
||||
@@ -173,13 +171,16 @@
|
||||
wsr.occurrence_end_time,
|
||||
wsr.id AS service_id,
|
||||
wsr.tenant_id,
|
||||
ad."name" AS service_name,
|
||||
mmd."name" AS service_name,
|
||||
ap."name" AS performer_name,
|
||||
al."name" AS org_name
|
||||
FROM wor_service_request wsr
|
||||
LEFT JOIN wor_activity_definition ad
|
||||
ON ad.id = wsr.activity_id
|
||||
AND ad.delete_flag = '0'
|
||||
LEFT JOIN med_medication_request mmr
|
||||
ON wsr.based_on_id = mmr.id
|
||||
AND mmr.delete_flag = '0'
|
||||
LEFT JOIN med_medication_definition mmd
|
||||
ON mmr.medication_id = mmd.id
|
||||
AND mmd.delete_flag = '0'
|
||||
LEFT JOIN adm_practitioner ap
|
||||
ON wsr.performer_id = ap.id
|
||||
AND ap.delete_flag = '0'
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<result property="merchandiseName" column="merchandise_name"/>
|
||||
<result property="traceNo" column="trace_no"/>
|
||||
<result property="partAttributeEnum" column="part_attribute_enum"/>
|
||||
<result property="dispenseEnum" column="dispense_enum"/>
|
||||
<collection property="inventoryDetailList" ofType="com.openhis.web.pharmacymanage.dto.InventoryDetailDto">
|
||||
<result property="inventoryId" column="inventory_id"/>
|
||||
<result property="maxUnitCode" column="max_unit_code"/>
|
||||
@@ -169,7 +170,8 @@
|
||||
ii.inventory_quantity,
|
||||
ii.inventory_lot_number,
|
||||
ii.expiration_date,
|
||||
ii.med_type_code
|
||||
ii.med_type_code,
|
||||
ii.dispense_enum
|
||||
FROM ( SELECT T8."name" AS department_name,
|
||||
T9.id AS doctor_id,
|
||||
T9."name" AS doctor_name,
|
||||
@@ -188,7 +190,7 @@
|
||||
T1.status_enum,
|
||||
T2.rate_code,
|
||||
T1.location_id,
|
||||
T1.method_code,
|
||||
T2.method_code,
|
||||
T1.lot_number,
|
||||
T2.dose_unit_code,
|
||||
T2.dispense_per_quantity,
|
||||
@@ -216,7 +218,8 @@
|
||||
T14.quantity AS inventory_quantity,
|
||||
T14.lot_number AS inventory_lot_number,
|
||||
T14.expiration_date,
|
||||
T15.med_type_code
|
||||
T15.med_type_code,
|
||||
T1.dispense_enum
|
||||
FROM med_medication_dispense AS T1
|
||||
LEFT JOIN med_medication_request AS T2
|
||||
ON T1.med_req_id = T2.id
|
||||
@@ -252,7 +255,7 @@
|
||||
ON T1.location_id = T13.id
|
||||
AND T13.delete_flag = '0'
|
||||
LEFT JOIN wor_inventory_item AS T14
|
||||
ON T2.medication_id = T14.item_id
|
||||
ON T1.medication_id = T14.item_id
|
||||
AND T1.location_id = T14.location_id
|
||||
AND T14.delete_flag = '0'
|
||||
LEFT JOIN adm_encounter_diagnosis AS T15
|
||||
|
||||
@@ -8,6 +8,8 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 就诊诊断管理Entity实体
|
||||
*
|
||||
@@ -86,5 +88,15 @@ public class EncounterDiagnosis extends HisBaseEntity {
|
||||
*/
|
||||
private Integer longTermFlag;
|
||||
|
||||
/**
|
||||
* 发病日期
|
||||
*/
|
||||
private Date onsetDate;
|
||||
|
||||
/**
|
||||
* 诊断日期
|
||||
*/
|
||||
private Date diagnosisTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.openhis.administration.mapper.EncounterParticipantMapper;
|
||||
import com.openhis.administration.service.IEncounterParticipantService;
|
||||
import com.openhis.common.enums.EncounterActivityStatus;
|
||||
import com.openhis.common.enums.ParticipantType;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -22,6 +23,7 @@ import java.util.List;
|
||||
* @author system
|
||||
* @date 2025-02-20
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class EncounterParticipantServiceImpl extends ServiceImpl<EncounterParticipantMapper, EncounterParticipant>
|
||||
implements IEncounterParticipantService {
|
||||
@@ -57,10 +59,16 @@ public class EncounterParticipantServiceImpl extends ServiceImpl<EncounterPartic
|
||||
*/
|
||||
@Override
|
||||
public void creatEncounterParticipants(Long encounterId, Date startTime, Long practitionerId, String typeCode) {
|
||||
log.info("创建参与者 - encounterId: {}, startTime: {}, practitionerId: {}, typeCode: {} (type: {}), status: {}",
|
||||
encounterId, startTime, practitionerId, typeCode, typeCode != null ? typeCode.getClass().getSimpleName() : "null", EncounterActivityStatus.ACTIVE.getValue());
|
||||
EncounterParticipant encounterParticipant = new EncounterParticipant();
|
||||
encounterParticipant.setEncounterId(encounterId).setStartTime(startTime).setPractitionerId(practitionerId)
|
||||
.setTypeCode(typeCode);
|
||||
baseMapper.insert(encounterParticipant);
|
||||
encounterParticipant.setEncounterId(encounterId)
|
||||
.setStartTime(startTime)
|
||||
.setPractitionerId(practitionerId)
|
||||
.setTypeCode(typeCode)
|
||||
.setStatusEnum(EncounterActivityStatus.ACTIVE.getValue());
|
||||
int result = baseMapper.insert(encounterParticipant);
|
||||
log.info("创建参与者结果 - encounterId: {}, typeCode: {}, result: {}, insertId: {}", encounterId, typeCode, result, encounterParticipant.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,7 +83,9 @@ public class EncounterParticipantServiceImpl extends ServiceImpl<EncounterPartic
|
||||
return baseMapper.update(null,
|
||||
new LambdaUpdateWrapper<EncounterParticipant>()
|
||||
.set(EncounterParticipant::getStatusEnum, EncounterActivityStatus.COMPLETED.getValue())
|
||||
.eq(EncounterParticipant::getEncounterId, encounterId).in(EncounterParticipant::getTypeCode,
|
||||
.eq(EncounterParticipant::getEncounterId, encounterId)
|
||||
.eq(EncounterParticipant::getStatusEnum, EncounterActivityStatus.ACTIVE.getValue())
|
||||
.in(EncounterParticipant::getTypeCode,
|
||||
ParticipantType.ATTENDING_DOCTOR.getCode(), ParticipantType.CHIEF_DOCTOR.getCode(),
|
||||
ParticipantType.PRIMARY_NURSE.getCode(), ParticipantType.ADMITTING_DOCTOR.getCode()));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.openhis.lab.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.openhis.lab.domain.InspectionType;
|
||||
|
||||
@@ -11,4 +13,13 @@ import com.openhis.lab.domain.InspectionType;
|
||||
*/
|
||||
public interface IInspectionTypeService extends IService<InspectionType> {
|
||||
|
||||
/**
|
||||
* 分页查询检验类型列表
|
||||
*
|
||||
* @param pageNo 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param searchKey 搜索关键词(可选)
|
||||
* @return 分页结果
|
||||
*/
|
||||
IPage<InspectionType> getPage(Integer pageNo, Integer pageSize, String searchKey);
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.openhis.lab.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.openhis.lab.domain.InspectionType;
|
||||
import com.openhis.lab.mapper.InspectionTypeMapper;
|
||||
import com.openhis.lab.service.IInspectionTypeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 检验类型Service实现类
|
||||
@@ -15,4 +19,22 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class InspectionTypeServiceImpl extends ServiceImpl<InspectionTypeMapper, InspectionType> implements IInspectionTypeService {
|
||||
|
||||
@Override
|
||||
public IPage<InspectionType> getPage(Integer pageNo, Integer pageSize, String searchKey) {
|
||||
Page<InspectionType> page = new Page<>(pageNo, pageSize);
|
||||
LambdaQueryWrapper<InspectionType> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
// 搜索关键词(按编码或名称模糊查询)
|
||||
if (StringUtils.hasText(searchKey)) {
|
||||
queryWrapper.and(wrapper -> wrapper
|
||||
.like(InspectionType::getCode, searchKey)
|
||||
.or()
|
||||
.like(InspectionType::getName, searchKey));
|
||||
}
|
||||
|
||||
// 按排序字段升序排列
|
||||
queryWrapper.orderByAsc(InspectionType::getSortOrder);
|
||||
|
||||
return this.page(page, queryWrapper);
|
||||
}
|
||||
}
|
||||
@@ -89,4 +89,7 @@ public class ActivityDefinition extends HisBaseEntity {
|
||||
|
||||
/** 服务范围 */
|
||||
private String serviceRange;
|
||||
|
||||
/** 检验类型ID(关联 inspection_type 表) */
|
||||
private Long inspectionTypeId;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openhis",
|
||||
"version": "3.8.8",
|
||||
"version": "3.8.9",
|
||||
"description": "OpenHIS管理系统",
|
||||
"author": "OpenHIS",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询所有检查类型列表(不分页,用于下拉选项)
|
||||
export function getAllCheckTypes() {
|
||||
return request({
|
||||
url: '/system/check-type/all',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 查询检查类型列表
|
||||
export function listCheckType(query) {
|
||||
return request({
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
* 从字典动态获取常量值,避免硬编码
|
||||
*
|
||||
* 使用方式:
|
||||
* import { DIAG_TYPE } from '@/utils/medicalConstants';
|
||||
* import { DIAG_TYPE, RequestStatus } from '@/utils/medicalConstants';
|
||||
* medTypeCode: DIAG_TYPE.WESTERN_MEDICINE
|
||||
* serviceStatus: RequestStatus.ACTIVE
|
||||
*/
|
||||
|
||||
import { getDicts } from '@/api/system/dict/data';
|
||||
@@ -12,6 +13,52 @@ import { getDicts } from '@/api/system/dict/data';
|
||||
// 诊断类型字典缓存
|
||||
let diagTypeCache = null;
|
||||
|
||||
/**
|
||||
* 请求状态枚举(与后端 RequestStatus.java 保持一致)
|
||||
* 用于服务申请、医嘱执行等状态管理
|
||||
*/
|
||||
export const RequestStatus = {
|
||||
/** 待发送 */
|
||||
DRAFT: 1,
|
||||
/** 已发送/待执行 */
|
||||
ACTIVE: 2,
|
||||
/** 已完成 */
|
||||
COMPLETED: 3,
|
||||
/** 暂停 */
|
||||
ON_HOLD: 4,
|
||||
/** 取消/待退 */
|
||||
CANCELLED: 5,
|
||||
/** 停嘱 */
|
||||
STOPPED: 6,
|
||||
/** 不执行 */
|
||||
ENDED: 7,
|
||||
/** 未知 */
|
||||
UNKNOWN: 9,
|
||||
};
|
||||
|
||||
/**
|
||||
* 请求状态枚举的说明信息
|
||||
*/
|
||||
export const RequestStatusDescriptions = {
|
||||
1: '待发送',
|
||||
2: '已发送/待执行',
|
||||
3: '已完成',
|
||||
4: '暂停',
|
||||
5: '取消/待退',
|
||||
6: '停嘱',
|
||||
7: '不执行',
|
||||
9: '未知',
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取请求状态的说明
|
||||
* @param {number} value - 请求状态值
|
||||
* @returns {string} - 说明信息
|
||||
*/
|
||||
export function getRequestStatusDescription(value) {
|
||||
return RequestStatusDescriptions[value] || '未知状态';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取诊断类型字典(异步初始化)
|
||||
*/
|
||||
|
||||
@@ -241,11 +241,21 @@ export function tansParams(params) {
|
||||
var part = encodeURIComponent(propName) + "=";
|
||||
if (value !== null && value !== "" && typeof (value) !== "undefined") {
|
||||
if (typeof value === 'object') {
|
||||
for (const key of Object.keys(value)) {
|
||||
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
|
||||
let params = propName + '[' + key + ']';
|
||||
var subPart = encodeURIComponent(params) + "=";
|
||||
result += subPart + encodeURIComponent(value[key]) + "&";
|
||||
// 处理数组类型
|
||||
if (Array.isArray(value)) {
|
||||
for (const item of value) {
|
||||
if (item !== null && item !== "" && typeof (item) !== 'undefined') {
|
||||
result += part + encodeURIComponent(item) + "&";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 处理对象类型
|
||||
for (const key of Object.keys(value)) {
|
||||
if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
|
||||
let params = propName + '[' + key + ']';
|
||||
var subPart = encodeURIComponent(params) + "=";
|
||||
result += subPart + encodeURIComponent(value[key]) + "&";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -467,7 +467,7 @@ function getDeptTree() {
|
||||
|
||||
/** 查询地点下拉树结构 */
|
||||
function getLocationTree() {
|
||||
locationTreeSelect({ formList: '11,16' }).then((response) => {
|
||||
locationTreeSelect({ formList: '11,16,17' }).then((response) => {
|
||||
locationOptions.value = response.data.records;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ import {
|
||||
} from './component/api';
|
||||
import AdviceListDialog from './component/adviceListDialog.vue';
|
||||
import {formatDate, formatDateStr} from '@/utils/index';
|
||||
import { RequestStatus } from '@/utils/medicalConstants';
|
||||
|
||||
const showSearch = ref(true);
|
||||
const total = ref(1);
|
||||
@@ -210,7 +211,7 @@ const data = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined,
|
||||
serviceStatus: 3, // 默认值为已完成 (对应 RequestStatus.COMPLETED)
|
||||
serviceStatus: RequestStatus.ACTIVE, // 默认值为待执行
|
||||
},
|
||||
});
|
||||
const { queryParams } = toRefs(data);
|
||||
|
||||
@@ -120,7 +120,7 @@ function getCategoryName(row) {
|
||||
}
|
||||
|
||||
return '-';
|
||||
} else if (row.adviceType === 2) { // 耗材类型
|
||||
} else if (row.adviceType === 2 || row.adviceType === 4) { // 🔧 Bug Fix: 耗材类型(2 或 4)
|
||||
return '耗材';
|
||||
} else if (row.adviceType === 3) { // 诊疗类型
|
||||
// 对于诊疗类型,activityType 就是 category_code 的整数值,使用 activityType_dictText 显示
|
||||
@@ -359,6 +359,7 @@ async function getList() {
|
||||
priceList: item.price ? [{ price: item.price }] : (item.retailPrice ? [{ price: item.retailPrice }] : []),
|
||||
inventoryList: [],
|
||||
adviceDefinitionId: item.id,
|
||||
adviceTableName: 'adm_device_definition', // 🔧 Bug #177 修复:添加耗材表名,用于后端库存匹配
|
||||
chargeItemDefinitionId: item.id,
|
||||
positionId: item.locationId,
|
||||
positionName: item.locationId_dictText || '',
|
||||
|
||||
@@ -949,7 +949,23 @@ export function deleteInspectionApplication(applyNo) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取检验类型列表(分类)
|
||||
* 分页获取检验类型列表(分类)
|
||||
* @param {Object} queryParams - 查询参数
|
||||
* @param {number} queryParams.pageNo - 页码
|
||||
* @param {number} queryParams.pageSize - 每页数量
|
||||
* @param {string} queryParams.searchKey - 搜索关键词
|
||||
*/
|
||||
export function getInspectionTypePage(queryParams) {
|
||||
return request({
|
||||
url: '/system/inspection-type/page',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取检验类型列表(不分页,兼容旧接口)
|
||||
* @deprecated 建议使用 getInspectionTypePage 分页接口
|
||||
*/
|
||||
export function getInspectionTypeList() {
|
||||
return request({
|
||||
@@ -965,6 +981,7 @@ export function getInspectionTypeList() {
|
||||
* @param {number} queryParams.pageNo - 页码
|
||||
* @param {number} queryParams.pageSize - 每页数量
|
||||
* @param {string} queryParams.categoryCode - 目录类别编码(检验)
|
||||
* @param {string} queryParams.inspectionTypeId - 检验类型ID列表,多个用逗号分隔
|
||||
*/
|
||||
export function getInspectionItemList(queryParams) {
|
||||
return request({
|
||||
|
||||
@@ -73,18 +73,12 @@
|
||||
</div>
|
||||
|
||||
<el-form :model="form" :rules="rules" ref="formRef">
|
||||
<el-table ref="diagnosisTableRef" :data="form.diagnosisList" height="650">
|
||||
<el-table ref="diagnosisTableRef" :data="form.diagnosisList" height="650" border>
|
||||
<el-table-column label="序号" type="index" width="50" />
|
||||
<el-table-column label="分类" align="center" prop="classification" width="120">
|
||||
<el-table-column label="分类" align="center" prop="classification" width="100">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.classification`">
|
||||
<!-- <el-select v-model="scope.row.classification" placeholder=" " style="width: 100px">
|
||||
<el-option label="西医" value="西医" />
|
||||
<el-option label="中医" value="中医" />
|
||||
<el-option label="证型" value="证型" />
|
||||
<el-option label="其他" value="其他" />
|
||||
</el-select>-->
|
||||
<el-select v-model="scope.row.classification" placeholder=" " style="width: 100px">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.classification`" style="margin-bottom: 0;">
|
||||
<el-select v-model="scope.row.classification" placeholder=" " style="width: 90px">
|
||||
<el-option
|
||||
v-for="item in diagnosis_classification"
|
||||
:key="item.value"
|
||||
@@ -95,10 +89,10 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断类型" align="center" prop="medTypeCode" width="180">
|
||||
<el-table-column label="诊断类型" align="center" prop="medTypeCode" width="150">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.medTypeCode`" :rules="rules.medTypeCode">
|
||||
<el-select v-model="scope.row.medTypeCode" placeholder=" " style="width: 150px">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.medTypeCode`" :rules="rules.medTypeCode" style="margin-bottom: 0;">
|
||||
<el-select v-model="scope.row.medTypeCode" placeholder=" " style="width: 130px">
|
||||
<el-option
|
||||
v-for="item in diag_type"
|
||||
:key="item.value"
|
||||
@@ -109,37 +103,57 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断" align="center" prop="name" >
|
||||
<el-table-column label="诊断" align="center" prop="name" min-width="220">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.name`" :rules="rules.name">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.name`" :rules="rules.name" style="margin-bottom: 0;">
|
||||
<el-popover
|
||||
:popper-style="{ padding: '0' }"
|
||||
:popper-style="{ padding: '0', width: '600px' }"
|
||||
placement="bottom-start"
|
||||
:visible="scope.row.showPopover"
|
||||
trigger="manual"
|
||||
:width="800"
|
||||
:show-arrow="false"
|
||||
>
|
||||
<template #default>
|
||||
<diagnosislist
|
||||
:diagnosisSearchkey="diagnosisSearchkey"
|
||||
@selectDiagnosis="handleSelsectDiagnosis"
|
||||
/>
|
||||
<div class="diagnosis-popover-container">
|
||||
<div class="diagnosis-popover-header">
|
||||
<span class="diagnosis-popover-title">选择诊断</span>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
:icon="Close"
|
||||
@click="closeDiagnosisPopover(scope.row)"
|
||||
class="diagnosis-popover-close"
|
||||
>关闭</el-button>
|
||||
</div>
|
||||
<div class="diagnosis-popover-body">
|
||||
<diagnosislist
|
||||
:diagnosisSearchkey="diagnosisSearchkey"
|
||||
@selectDiagnosis="(row) => handleSelectDiagnosis(row, scope.row, scope.$index)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #reference>
|
||||
<el-input v-model="scope.row.name" placeholder="请选择诊断" @input="handleChange"
|
||||
@focus="handleFocus(scope.row, scope.$index)" @blur="handleBlur(scope.row)" />
|
||||
<div
|
||||
class="diagnosis-text"
|
||||
@click="handleFocus(scope.row, scope.$index)"
|
||||
:title="scope.row.name || '点击选择诊断'"
|
||||
>
|
||||
<span class="diagnosis-text-content">{{ scope.row.name || '点击选择诊断' }}</span>
|
||||
<el-icon class="diagnosis-text-icon"><ArrowDown /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="主诊断" align="center" prop="maindiseFlag" width="100">
|
||||
<el-table-column label="主诊断" align="center" prop="maindiseFlag" width="90">
|
||||
<template #default="scope">
|
||||
<el-form-item style="display: flex;justify-content: center;margin-bottom: 0;">
|
||||
<el-select
|
||||
v-model="scope.row.maindiseFlag"
|
||||
placeholder=" "
|
||||
style="width: 80px"
|
||||
style="width: 70px"
|
||||
@change="(value) => handleMaindise(value, scope.$index)"
|
||||
>
|
||||
<el-option label="是" :value="1" />
|
||||
@@ -148,21 +162,21 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断备注" align="center" prop="diagnosisDesc" width="180">
|
||||
<el-table-column label="诊断备注" align="center" prop="diagnosisDesc" width="150">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.diagnosisDesc`">
|
||||
<el-input v-model="scope.row.diagnosisDesc" placeholder="请输入备注" />
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.diagnosisDesc`" style="margin-bottom: 0;">
|
||||
<el-input v-model="scope.row.diagnosisDesc" placeholder="请输入备注" style="width: 130px" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="ICD代码" align="center" prop="ybNo" width="180" />
|
||||
<el-table-column label="诊断状态" align="center" prop="verificationStatusEnum" width="120">
|
||||
<el-table-column label="ICD代码" align="center" prop="ybNo" width="150" />
|
||||
<el-table-column label="诊断状态" align="center" prop="verificationStatusEnum" width="100">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.verificationStatusEnum`" style="margin-bottom: 0;">
|
||||
<el-select
|
||||
v-model="scope.row.verificationStatusEnum"
|
||||
placeholder=" "
|
||||
style="width: 100%"
|
||||
style="width: 90px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in diagnosisOptions"
|
||||
@@ -174,37 +188,37 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="发病日期" align="center" prop="onsetDate" width="160">
|
||||
<el-table-column label="发病日期" align="center" prop="onsetDate" width="140">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.onsetDate`">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.onsetDate`" style="margin-bottom: 0;">
|
||||
<el-date-picker
|
||||
v-model="scope.row.onsetDate"
|
||||
type="date"
|
||||
placeholder=" "
|
||||
style="width: 100%"
|
||||
style="width: 130px"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="诊断日期" align="center" prop="diagnosisTime" width="160">
|
||||
<el-table-column label="诊断日期" align="center" prop="diagnosisTime" width="140">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.diagnosisTime`">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.diagnosisTime`" style="margin-bottom: 0;">
|
||||
<el-date-picker
|
||||
v-model="scope.row.diagnosisTime"
|
||||
type="date"
|
||||
placeholder=" "
|
||||
style="width: 100%"
|
||||
style="width: 130px"
|
||||
value-format="YYYY-MM-DD"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="医生" align="center" prop="diagnosisDoctor" width="120" />
|
||||
<el-table-column label="长效诊断标识" align="center" prop="longTermFlag" width="140">
|
||||
<el-table-column label="医生" align="center" prop="diagnosisDoctor" width="100" />
|
||||
<el-table-column label="长效诊断标识" align="center" prop="longTermFlag" width="110">
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.longTermFlag`">
|
||||
<el-select v-model="scope.row.longTermFlag" placeholder=" " style="width: 100%">
|
||||
<el-form-item :prop="`diagnosisList.${scope.$index}.longTermFlag`" style="margin-bottom: 0;">
|
||||
<el-select v-model="scope.row.longTermFlag" placeholder=" " style="width: 90px">
|
||||
<el-option
|
||||
v-for="item in long_term_flag"
|
||||
:key="item.value"
|
||||
@@ -250,6 +264,7 @@
|
||||
|
||||
<script setup>
|
||||
import {getCurrentInstance} from 'vue';
|
||||
import { Close, ArrowDown } from '@element-plus/icons-vue';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import {
|
||||
delEncounterDiagnosis,
|
||||
@@ -405,7 +420,7 @@ function handleImport() {
|
||||
res.data.forEach((item, index) => {
|
||||
form.value.diagnosisList.push({
|
||||
...item,
|
||||
...{
|
||||
...{
|
||||
medTypeCode: DIAG_TYPE.WESTERN_MEDICINE, // 诊断类型:西医诊断 (值:1)
|
||||
verificationStatusEnum: 4,
|
||||
definitionId: item.id,
|
||||
@@ -415,7 +430,8 @@ function handleImport() {
|
||||
classification: '西医', // 导入的慢性病默认为西医
|
||||
onsetDate: getCurrentDate(),
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: getCurrentDate()
|
||||
diagnosisTime: getCurrentDate(),
|
||||
longTermFlag: 0 // 默认非长效诊断
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -519,7 +535,8 @@ function handleAddDiagnosis() {
|
||||
classification: '西医', // 默认为西医
|
||||
onsetDate: getCurrentDate(),
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: getCurrentDate()
|
||||
diagnosisTime: getCurrentDate(),
|
||||
longTermFlag: 0 // 默认非长效诊断
|
||||
});
|
||||
|
||||
// 添加后按排序号排序
|
||||
@@ -611,14 +628,18 @@ async function handleSaveDiagnosis() {
|
||||
// 开始加载状态,防止重复提交
|
||||
saveLoading.value = true;
|
||||
|
||||
// 保存前按排序号排序
|
||||
form.value.diagnosisList.sort((a, b) => (a.diagSrtNo || 0) - (b.diagSrtNo || 0));
|
||||
// 保存前按排序号排序,并转换日期格式
|
||||
const diagnosisChildList = form.value.diagnosisList.map(item => ({
|
||||
...item,
|
||||
onsetDate: item.onsetDate ? new Date(item.onsetDate) : null,
|
||||
diagnosisTime: item.diagnosisTime ? new Date(item.diagnosisTime) : null
|
||||
}));
|
||||
|
||||
// 调用保存诊断接口
|
||||
const res = await saveDiagnosis({
|
||||
patientId: props.patientInfo.patientId,
|
||||
encounterId: props.patientInfo.encounterId,
|
||||
diagnosisChildList: form.value.diagnosisList,
|
||||
diagnosisChildList: diagnosisChildList,
|
||||
});
|
||||
|
||||
if (res.code === 200) {
|
||||
@@ -714,12 +735,22 @@ function handleChange(value) {
|
||||
/**
|
||||
* 选择诊断并赋值到列表
|
||||
*/
|
||||
function handleSelsectDiagnosis(row) {
|
||||
console.log(row);
|
||||
form.value.diagnosisList[rowIndex.value].ybNo = row.ybNo;
|
||||
form.value.diagnosisList[rowIndex.value].name = row.name;
|
||||
form.value.diagnosisList[rowIndex.value].definitionId = row.id;
|
||||
function handleSelectDiagnosis(row, rowData, index) {
|
||||
console.log('选择诊断:', row);
|
||||
rowData.name = row.name;
|
||||
rowData.ybNo = row.ybNo;
|
||||
rowData.definitionId = row.id;
|
||||
rowData.showPopover = false;
|
||||
emits('diagnosisSave', false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭诊断选择弹窗
|
||||
*/
|
||||
function closeDiagnosisPopover(row) {
|
||||
row.showPopover = false;
|
||||
}
|
||||
|
||||
/**获取焦点时 打开列表 */
|
||||
function handleFocus(row, index) {
|
||||
if(row.typeName==='中医诊断'){
|
||||
@@ -736,16 +767,16 @@ function handleFocus(row, index) {
|
||||
});
|
||||
openAddDiagnosisDialog.value = true;
|
||||
}else{
|
||||
// 关闭其他行的弹窗
|
||||
form.value.diagnosisList.forEach((item, idx) => {
|
||||
if (idx !== index) {
|
||||
item.showPopover = false;
|
||||
}
|
||||
});
|
||||
rowIndex.value = index;
|
||||
row.showPopover = true;
|
||||
}
|
||||
|
||||
}
|
||||
/**失去焦点时 关闭列表 */
|
||||
function handleBlur(row) {
|
||||
row.showPopover = false;
|
||||
}
|
||||
|
||||
function handleNodeClick(data) {
|
||||
console.log(data.children);
|
||||
// 检查节点是否为根节点
|
||||
@@ -823,4 +854,89 @@ defineExpose({ getList, getDetail, handleSaveDiagnosis });
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.diagnosis-text {
|
||||
min-height: 32px;
|
||||
line-height: 1.4;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
word-break: break-all;
|
||||
white-space: pre-wrap;
|
||||
max-width: 200px;
|
||||
transition: border-color 0.2s;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.diagnosis-text:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.diagnosis-text-content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.diagnosis-text-icon {
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.diagnosis-text:hover .diagnosis-text-icon {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
/* 诊断选择弹窗样式 */
|
||||
.diagnosis-popover-container {
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.diagnosis-popover-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.diagnosis-popover-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.diagnosis-popover-close {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.diagnosis-popover-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.diagnosis-text:empty::before {
|
||||
content: '点击选择诊断';
|
||||
color: #a8abb2;
|
||||
}
|
||||
|
||||
.diagnosis-text:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.diagnosis-text:empty::before {
|
||||
content: '请选择诊断';
|
||||
color: #a8abb2;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,21 +1,48 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="diagnosis-list-container">
|
||||
<div class="diagnosis-search-box">
|
||||
<el-input
|
||||
v-model="searchText"
|
||||
placeholder="输入诊断名称或ICD代码搜索"
|
||||
clearable
|
||||
@keyup.enter="handleSearch"
|
||||
@clear="handleClear"
|
||||
>
|
||||
<template #append>
|
||||
<el-button :icon="Search" @click="handleSearch" />
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<el-table
|
||||
ref="diagnosisDefinitionRef"
|
||||
:data="diagnosisDefinitionList"
|
||||
row-key="patientId"
|
||||
row-key="id"
|
||||
@cell-click="clickRow"
|
||||
max-height="400"
|
||||
max-height="350"
|
||||
highlight-current-row
|
||||
border
|
||||
>
|
||||
<el-table-column label="诊断名称" align="center" prop="name" />
|
||||
<el-table-column label="ICD代码" align="center" prop="ybNo" />
|
||||
<el-table-column label="诊断类型" align="center" prop="typeName" width="180"/>
|
||||
<el-table-column label="诊断名称" align="left" prop="name" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="ICD代码" align="center" prop="ybNo" width="120" />
|
||||
<el-table-column label="诊断类型" align="center" prop="typeName" width="100" />
|
||||
</el-table>
|
||||
<div class="diagnosis-pagination" v-if="total > queryParams.pageSize">
|
||||
<el-pagination
|
||||
small
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="queryParams.pageSize"
|
||||
:current-page="queryParams.pageNo"
|
||||
@current-change="handlePageChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {getDiagnosisDefinitionList} from '../api';
|
||||
import { ref, watch } from 'vue';
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { getDiagnosisDefinitionList } from '../api';
|
||||
|
||||
const props = defineProps({
|
||||
diagnosisSearchkey: {
|
||||
@@ -23,36 +50,87 @@ const props = defineProps({
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['selectDiagnosis']);
|
||||
|
||||
const searchText = ref('');
|
||||
const total = ref(0);
|
||||
const queryParams = ref({
|
||||
pageSize: 1000,
|
||||
pageSize: 10,
|
||||
pageNo: 1,
|
||||
// typeCode: 1,
|
||||
});
|
||||
const diagnosisDefinitionList = ref([]);
|
||||
|
||||
// 监听外部传入的搜索关键字
|
||||
watch(
|
||||
() => props.diagnosisSearchkey,
|
||||
(newValue) => {
|
||||
searchText.value = newValue;
|
||||
queryParams.value.searchKey = newValue;
|
||||
queryParams.value.pageNo = 1;
|
||||
getList();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
getList();
|
||||
// 获取诊断列表
|
||||
function getList() {
|
||||
getDiagnosisDefinitionList(queryParams.value).then((res) => {
|
||||
diagnosisDefinitionList.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
diagnosisDefinitionList.value = res.data.records || [];
|
||||
total.value = res.data.total || 0;
|
||||
});
|
||||
}
|
||||
|
||||
// 搜索
|
||||
function handleSearch() {
|
||||
queryParams.value.searchKey = searchText.value;
|
||||
queryParams.value.pageNo = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
// 清空搜索
|
||||
function handleClear() {
|
||||
searchText.value = '';
|
||||
queryParams.value.searchKey = '';
|
||||
queryParams.value.pageNo = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
// 分页变化
|
||||
function handlePageChange(page) {
|
||||
queryParams.value.pageNo = page;
|
||||
getList();
|
||||
}
|
||||
|
||||
// 点击行选择诊断
|
||||
function clickRow(row) {
|
||||
emit('selectDiagnosis', row);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.diagnosis-list-container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.diagnosis-search-box {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
.diagnosis-pagination {
|
||||
padding: 8px 16px;
|
||||
border-top: 1px solid #e4e7ed;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
:deep(.el-table__row) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:deep(.el-table__row:hover) {
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -22,9 +22,10 @@
|
||||
@click="handleDiagnosisChange(item)" />
|
||||
</el-select>
|
||||
<span class="descriptions-item-label"> 费用性质: </span>
|
||||
<el-select v-model="accountId" placeholder="费用性质" style="width: 180px">
|
||||
<el-option v-for="item in contractList" :key="item.accountId" :label="item.contractName"
|
||||
:value="item.accountId" />
|
||||
<el-select v-model="accountId" placeholder="费用性质" style="width: 180px"
|
||||
value-key="accountId" :filterable="true">
|
||||
<el-option v-for="item in contractList" :key="item.accountId"
|
||||
:label="item.contractName || '自费'" :value="item.accountId" />
|
||||
</el-select>
|
||||
<span class="descriptions-item-label">
|
||||
合计金额:{{ totalAmount ? totalAmount.toFixed(2) : 0 }}元
|
||||
@@ -691,6 +692,7 @@ const unitMap = ref({
|
||||
const buttonDisabled = computed(() => {
|
||||
return !props.patientInfo;
|
||||
});
|
||||
|
||||
const props = defineProps({
|
||||
patientInfo: {
|
||||
type: Object,
|
||||
@@ -1245,8 +1247,33 @@ function getListInfo(addNewRow) {
|
||||
priceInfo.value = res.data;
|
||||
}),
|
||||
getContract({ encounterId: props.patientInfo.encounterId }).then((res) => {
|
||||
contractList.value = res.data;
|
||||
accountId.value = props.patientInfo.accountId;
|
||||
// 🔧 Bug Fix: 确保 contractList 是数组
|
||||
let contractData = res.data;
|
||||
if (!contractData || !Array.isArray(contractData)) {
|
||||
contractData = [];
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix: 处理返回的费用性质数据,如果没有contractName或为空,显示"自费"
|
||||
if (contractData.length > 0) {
|
||||
contractList.value = contractData.map(item => {
|
||||
// 如果 contractName 为空/undefined/null,显示"自费"
|
||||
const contractName = item.contractName;
|
||||
if (!contractName || contractName === '' || contractName === null) {
|
||||
return { ...item, contractName: '自费' };
|
||||
}
|
||||
return item;
|
||||
});
|
||||
} else {
|
||||
// 没有数据时添加默认"自费"选项
|
||||
contractList.value = [{ accountId: 0, contractName: '自费' }];
|
||||
}
|
||||
|
||||
// 设置默认选中的费用性质
|
||||
// 优先使用 contractList 中的第一个选项
|
||||
if (contractList.value.length > 0) {
|
||||
accountId.value = contractList.value[0].accountId;
|
||||
}
|
||||
console.log('费用性质数据:', contractList.value, '选中:', accountId.value);
|
||||
})
|
||||
]);
|
||||
|
||||
@@ -1267,7 +1294,15 @@ function getListInfo(addNewRow) {
|
||||
contentJson?.consultationRequestId;
|
||||
|
||||
let adviceType = item.adviceType;
|
||||
let adviceType_dictText = item.adviceType_dictText || mapAdviceTypeLabel(item.adviceType);
|
||||
|
||||
// 🔧 Bug Fix: 后端保存时将耗材(4)转换为中成药(2),显示时需要转换回来
|
||||
// 检查 adviceTableName,如果是耗材表则应该是耗材类型
|
||||
const adviceTableName = contentJson?.adviceTableName || item.adviceTableName;
|
||||
if (adviceType === 2 && adviceTableName === 'adm_device_definition') {
|
||||
adviceType = 4; // 后端2(中成药) -> 前端4(耗材)
|
||||
}
|
||||
|
||||
let adviceType_dictText = item.adviceType_dictText || mapAdviceTypeLabel(adviceType);
|
||||
|
||||
// 如果是会诊类型,设置为会诊类型
|
||||
if (isConsultation) {
|
||||
@@ -1716,7 +1751,15 @@ function handleSave(prescriptionId) {
|
||||
}
|
||||
|
||||
// 验证费用性质是否已选择
|
||||
if (!accountId.value) {
|
||||
// 🔧 Bug Fix: 允许 'ZIFEI' 作为有效值
|
||||
if (!accountId.value && accountId.value !== 'ZIFEI') {
|
||||
proxy.$modal.msgWarning('请先选择费用性质');
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证费用性质是否已选择
|
||||
// 🔧 Bug Fix: 允许 'ZIFEI' 或 0 作为有效值
|
||||
if (!accountId.value && accountId.value !== 'ZIFEI' && accountId.value !== 0) {
|
||||
proxy.$modal.msgWarning('请先选择费用性质');
|
||||
return;
|
||||
}
|
||||
@@ -1800,16 +1843,31 @@ function handleSave(prescriptionId) {
|
||||
|
||||
// 签发核心逻辑
|
||||
function executeSaveLogic() {
|
||||
// 🔧 Bug Fix: 获取当前选中的费用性质,如果是'ZIFEI'或0则转为null,让后端查询默认账户
|
||||
let finalAccountId = accountId.value;
|
||||
if (finalAccountId === 'ZIFEI' || finalAccountId === 0) {
|
||||
finalAccountId = null;
|
||||
} else if (finalAccountId && !isNaN(Number(finalAccountId))) {
|
||||
finalAccountId = Number(finalAccountId);
|
||||
} else {
|
||||
finalAccountId = null;
|
||||
}
|
||||
|
||||
saveList.forEach((item) => {
|
||||
item.patientId = props.patientInfo.patientId;
|
||||
item.encounterId = props.patientInfo.encounterId;
|
||||
item.accountId = props.patientInfo.accountId;
|
||||
item.accountId = finalAccountId;
|
||||
item.dbOpType = '1';
|
||||
});
|
||||
|
||||
loading.value = true;
|
||||
|
||||
let list = saveList.map((item) => {
|
||||
// 先解析contentJson
|
||||
let parsedContent = JSON.parse(item.contentJson || '{}');
|
||||
// 🔧 Bug Fix: 强制将accountId设为正确的值
|
||||
parsedContent.accountId = finalAccountId;
|
||||
|
||||
// --- 【修改点2:Bug 2 修复 (单位换算)】 ---
|
||||
let finalQuantity = item.quantity;
|
||||
let finalUnitCode = item.unitCode;
|
||||
@@ -1837,9 +1895,38 @@ function handleSave(prescriptionId) {
|
||||
saveAdviceType = 3; // 会诊:前端5 -> 后端3(诊疗类)
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix: Validate and fix NaN values before sending to backend
|
||||
if (item.totalPrice === undefined || item.totalPrice === null ||
|
||||
(typeof item.totalPrice === 'number' && (isNaN(item.totalPrice) || !isFinite(item.totalPrice)))) {
|
||||
item.totalPrice = '0.00';
|
||||
console.warn('Fixed NaN totalPrice for item:', item.adviceName);
|
||||
}
|
||||
|
||||
// 构造请求参数
|
||||
// 🔧 Bug Fix: 确保库存匹配成功的关键字段
|
||||
// 耗材使用 adm_device_definition 表
|
||||
let adviceTableNameVal = '';
|
||||
let locationIdVal = null;
|
||||
if (item.adviceType == 4) {
|
||||
adviceTableNameVal = 'adm_device_definition';
|
||||
locationIdVal = item.locationId || item.positionId;
|
||||
} else {
|
||||
adviceTableNameVal = item.adviceTableName || '';
|
||||
locationIdVal = item.locationId || item.positionId;
|
||||
}
|
||||
|
||||
console.log('保存医嘱参数:', {
|
||||
adviceName: item.adviceName,
|
||||
adviceType: item.adviceType,
|
||||
saveAdviceType: saveAdviceType,
|
||||
adviceTableName: adviceTableNameVal,
|
||||
locationId: locationIdVal,
|
||||
positionId: item.positionId,
|
||||
locationId2: item.locationId
|
||||
});
|
||||
|
||||
return {
|
||||
...JSON.parse(item.contentJson || JSON.stringify(item)), // 防止contentJson为空
|
||||
...parsedContent,
|
||||
adviceType: saveAdviceType, // 使用转换后的类型
|
||||
requestId: item.requestId,
|
||||
dbOpType: '1',
|
||||
@@ -1847,7 +1934,11 @@ function handleSave(prescriptionId) {
|
||||
uniqueKey: undefined,
|
||||
// 使用转换后的数量和单位
|
||||
quantity: finalQuantity,
|
||||
unitCode: finalUnitCode
|
||||
unitCode: finalUnitCode,
|
||||
totalPrice: item.totalPrice, // Ensure totalPrice is valid
|
||||
// 🔧 Bug Fix: 确保库存匹配成功的关键字段
|
||||
adviceTableName: adviceTableNameVal,
|
||||
locationId: locationIdVal
|
||||
};
|
||||
});
|
||||
|
||||
@@ -1982,6 +2073,13 @@ function handleOrderBindInfo(bindIdInfo) {
|
||||
});
|
||||
|
||||
list?.forEach((item) => {
|
||||
// 🔧 Bug #145 修复:确保用法绑定的耗材 adviceType 为 4(前端耗材类型值)
|
||||
// 后端返回的 adviceType=2,但前端统一使用 4 表示耗材
|
||||
// 必须在 setValue 之前修改,确保 setValue 方法走耗材处理逻辑
|
||||
if (item.adviceType === 2) {
|
||||
item.adviceType = 4;
|
||||
}
|
||||
|
||||
rowIndex.value = prescriptionList.value.length;
|
||||
setValue(item);
|
||||
|
||||
@@ -2069,7 +2167,8 @@ function handleSaveSign(row, index, prescriptionId) {
|
||||
}
|
||||
|
||||
// 验证费用性质是否已选择
|
||||
if (!accountId.value) {
|
||||
// 🔧 Bug Fix: 允许 'ZIFEI' 或 0 作为有效值
|
||||
if (!accountId.value && accountId.value !== 'ZIFEI' && accountId.value !== 0) {
|
||||
proxy.$modal.msgWarning('请先选择费用性质');
|
||||
return;
|
||||
}
|
||||
@@ -2253,17 +2352,32 @@ function handleSaveBatch(prescriptionId) {
|
||||
}
|
||||
|
||||
// 验证费用性质是否已选择
|
||||
// 🔧 Bug Fix: 检查是否选择了费用性质(允许 'ZIFEI' 或 0 作为有效值)
|
||||
let prescription = westernPrescriptions.value.find(p => p.id === targetPrescriptionId);
|
||||
if (prescription) {
|
||||
// 同步当前选择的费用性质到处方对象
|
||||
// 同步当前选择的费用性质到处方对象(保留原始值)
|
||||
prescription.accountId = accountId.value;
|
||||
}
|
||||
|
||||
if (!prescription || !prescription.accountId) {
|
||||
// 🔧 Bug Fix: 允许 'ZIFEI' 或 0 作为有效值
|
||||
if (!prescription || (!prescription.accountId && prescription.accountId !== 'ZIFEI' && prescription.accountId !== 0)) {
|
||||
proxy.$modal.msgWarning('请先选择费用性质');
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix: 在保存时才转换 accountId
|
||||
let finalAccountId = accountId.value;
|
||||
if (finalAccountId === 'ZIFEI') {
|
||||
finalAccountId = null;
|
||||
} else if (finalAccountId && !isNaN(Number(finalAccountId))) {
|
||||
finalAccountId = Number(finalAccountId);
|
||||
}
|
||||
|
||||
// 更新到处方对象
|
||||
if (prescription) {
|
||||
prescription.accountId = finalAccountId;
|
||||
}
|
||||
|
||||
// 获取对应处方的展开状态
|
||||
const prescriptionExpandOrder = prescription.expandOrder || [];
|
||||
if (prescriptionExpandOrder.length > 0) {
|
||||
@@ -2331,6 +2445,43 @@ function handleSaveBatch(prescriptionId) {
|
||||
};
|
||||
const contentJson = JSON.stringify(itemToSave);
|
||||
|
||||
// 🔧 Bug Fix: 处理accountId,如果是'ZIFEI'或0则转为null,让后端查询默认账户
|
||||
let itemAccountId = finalAccountId;
|
||||
if (itemAccountId === 'ZIFEI' || itemAccountId === 0) {
|
||||
itemAccountId = null;
|
||||
} else if (itemAccountId && !isNaN(Number(itemAccountId))) {
|
||||
itemAccountId = Number(itemAccountId);
|
||||
}
|
||||
|
||||
// 🔧 Bug Fix: 确保库存匹配成功的关键字段
|
||||
let adviceTableNameVal = '';
|
||||
let locationIdVal = null;
|
||||
|
||||
console.log('耗材 debug:', {
|
||||
adviceType: item.adviceType,
|
||||
positionId: item.positionId,
|
||||
locationId: item.locationId,
|
||||
adviceDefinitionId: item.adviceDefinitionId,
|
||||
adviceTableName: item.adviceTableName,
|
||||
// 完整对象
|
||||
item: item
|
||||
});
|
||||
|
||||
if (item.adviceType == 4) {
|
||||
adviceTableNameVal = 'adm_device_definition';
|
||||
locationIdVal = item.locationId || item.positionId;
|
||||
} else {
|
||||
adviceTableNameVal = item.adviceTableName || '';
|
||||
locationIdVal = item.locationId || item.positionId;
|
||||
}
|
||||
|
||||
console.log('处理后:', {
|
||||
adviceTableName: adviceTableNameVal,
|
||||
locationId: locationIdVal,
|
||||
adviceDefinitionId: item.adviceDefinitionId,
|
||||
adviceDefinitionIdType: typeof item.adviceDefinitionId
|
||||
});
|
||||
|
||||
return {
|
||||
...item,
|
||||
adviceType: saveAdviceType,
|
||||
@@ -2339,7 +2490,12 @@ function handleSaveBatch(prescriptionId) {
|
||||
prescriptionId: targetPrescriptionId,
|
||||
contentJson: contentJson,
|
||||
quantity: finalQuantity,
|
||||
unitCode: finalUnitCode
|
||||
unitCode: finalUnitCode,
|
||||
// 🔧 Bug Fix: 显式设置accountId
|
||||
accountId: itemAccountId,
|
||||
// 🔧 Bug Fix: 确保库存匹配成功
|
||||
adviceTableName: adviceTableNameVal,
|
||||
locationId: locationIdVal
|
||||
};
|
||||
});
|
||||
// --- 【修改结束】 ---
|
||||
@@ -2354,6 +2510,9 @@ function handleSaveBatch(prescriptionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔧 调试:查看保存时的完整参数
|
||||
console.log('【保存】完整请求参数:', JSON.stringify(saveList, null, 2));
|
||||
|
||||
isSaving.value = true;
|
||||
|
||||
// 本地临时更新状态,让用户立即看到保存效果
|
||||
@@ -2498,13 +2657,27 @@ function setValue(row) {
|
||||
// 🔧 Bug #147 修复:耗材类型(adviceType=4)的专门处理
|
||||
// 耗材从getDeviceList接口获取,使用priceList中的价格
|
||||
if (row.priceList && row.priceList.length > 0) {
|
||||
prescriptionList.value[rowIndex.value].unitPrice = row.priceList[0].price;
|
||||
prescriptionList.value[rowIndex.value].unitTempPrice = row.priceList[0].price;
|
||||
prescriptionList.value[rowIndex.value].minUnitPrice = row.priceList[0].price;
|
||||
// 🔧 Bug Fix: Add validation to prevent NaN values in totalPrice
|
||||
const price = row.priceList[0].price;
|
||||
const validPrice = (price !== undefined && price !== null && !isNaN(price) && isFinite(price))
|
||||
? Number(price)
|
||||
: 0;
|
||||
|
||||
prescriptionList.value[rowIndex.value].unitPrice = validPrice;
|
||||
prescriptionList.value[rowIndex.value].unitTempPrice = validPrice;
|
||||
prescriptionList.value[rowIndex.value].minUnitPrice = validPrice;
|
||||
prescriptionList.value[rowIndex.value].quantity = 1;
|
||||
prescriptionList.value[rowIndex.value].totalPrice = row.priceList[0].price;
|
||||
prescriptionList.value[rowIndex.value].totalPrice = validPrice;
|
||||
prescriptionList.value[rowIndex.value].positionName = row.positionName || '';
|
||||
prescriptionList.value[rowIndex.value].locationId = row.positionId;
|
||||
// 🔧 Bug Fix: 使用 positionId,如果为空则使用患者信息中的 orgId
|
||||
console.log('设置耗材locationId:', {
|
||||
rowPositionId: row.positionId,
|
||||
patientOrgId: props.patientInfo.orgId,
|
||||
patientInfo: props.patientInfo
|
||||
});
|
||||
const finalLocationId = row.positionId || props.patientInfo.orgId;
|
||||
prescriptionList.value[rowIndex.value].locationId = finalLocationId;
|
||||
prescriptionList.value[rowIndex.value].positionId = finalLocationId;
|
||||
}
|
||||
} else {
|
||||
getOrgList();
|
||||
@@ -2856,7 +3029,8 @@ function getGroupMarkers() {
|
||||
// 计算总价
|
||||
function calculateTotalPrice(row, index) {
|
||||
nextTick(() => {
|
||||
if (row.adviceType == 3) {
|
||||
// 🔧 Bug Fix: Handle consumables (adviceType=4) and projects (adviceType=3) the same way
|
||||
if (row.adviceType == 3 || row.adviceType == 4) {
|
||||
// 检查价格是否为有效数字
|
||||
if (row.unitPrice !== undefined && row.unitPrice !== null && !isNaN(row.unitPrice) && isFinite(row.unitPrice)) {
|
||||
row.totalPrice = (row.unitPrice * row.quantity).toFixed(6);
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
</el-radio-group>
|
||||
<el-button type="primary" plain @click.stop="handleFinish(patientInfo.encounterId)" size="small">完诊</el-button>
|
||||
<el-button type="primary" plain @click.stop="handleLeave(patientInfo.encounterId)" size="small">暂离</el-button>
|
||||
<el-button type="warning" plain :disabled="isCancelButtonDisabled" @click.stop="handleCancel(patientInfo.encounterId)" size="small">取消接诊</el-button>
|
||||
<el-button type="primary" plain :disabled="isRefundButtonDisabled" @click.stop="handleRefund(patientInfo.encounterId)" size="small">退费</el-button>
|
||||
<el-button type="primary" plain class="top-layer-btn" @click.stop="getEnPrescription(patientInfo.encounterId)" size="small">处方单</el-button>
|
||||
<el-button type="primary" plain class="top-layer-btn" :disabled="isHospitalizationButtonDisabled" @click.stop="handleHospitalizationClick()" size="small">办理住院</el-button>
|
||||
@@ -193,6 +194,7 @@ import {
|
||||
getList,
|
||||
isHospitalization,
|
||||
leaveEncounter,
|
||||
cancelEncounter,
|
||||
} from './components/api.js';
|
||||
import prescriptionlist from './components/prescription/prescriptionlist.vue';
|
||||
import RefundListDialog from './components/prescription/refundListDialog.vue';
|
||||
@@ -282,6 +284,16 @@ const isHospitalizationButtonDisabled = computed(() => {
|
||||
patientInfo.value.encounterId === undefined;
|
||||
});
|
||||
|
||||
// 计算属性:确定取消接诊按钮是否应被禁用
|
||||
const isCancelButtonDisabled = computed(() => {
|
||||
return !patientInfo.value ||
|
||||
typeof patientInfo.value !== 'object' ||
|
||||
!patientInfo.value.encounterId ||
|
||||
patientInfo.value.encounterId === '' ||
|
||||
patientInfo.value.encounterId === null ||
|
||||
patientInfo.value.encounterId === undefined;
|
||||
});
|
||||
|
||||
// 计算属性:确定退费按钮是否应被禁用(与住院按钮使用相同的逻辑)
|
||||
const isRefundButtonDisabled = computed(() => {
|
||||
return !patientInfo.value ||
|
||||
@@ -628,6 +640,34 @@ function handleLeave(encounterId) {
|
||||
});
|
||||
}
|
||||
|
||||
function handleCancel(encounterId) {
|
||||
if (!encounterId) {
|
||||
ElMessage.warning('请先选择患者后再进行取消接诊操作');
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm('确定要取消接诊该患者吗?取消后患者将回到待诊状态。', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
cancelEncounter(encounterId).then((res) => {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('取消接诊成功');
|
||||
patientInfo.value = {};
|
||||
getPatientList();
|
||||
getWaitPatient();
|
||||
} else {
|
||||
proxy.$modal.msgError(res.msg || '取消接诊失败');
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error('取消接诊失败:', error);
|
||||
proxy.$modal.msgError('取消接诊失败');
|
||||
});
|
||||
}).catch(() => {
|
||||
// 用户取消操作,不做处理
|
||||
});
|
||||
}
|
||||
|
||||
async function handleFinish(encounterId) {
|
||||
// 完诊前验证诊断信息
|
||||
try {
|
||||
|
||||
@@ -206,3 +206,14 @@ export function getAllWards(params = {}) {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前登录用户有权限管理的病区
|
||||
*/
|
||||
export function getPractitionerWard(queryParams) {
|
||||
return request({
|
||||
url: '/app-common/practitioner-ward',
|
||||
method: 'get',
|
||||
params: queryParams,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -29,16 +29,16 @@
|
||||
<el-table-column prop="patientName" align="center" label="患者姓名" />
|
||||
<el-table-column prop="genderEnum_enumText" label="性别" align="center" />
|
||||
<el-table-column label="年龄" align="center">
|
||||
<template #default="scope">
|
||||
{{ scope.row.age ? `${scope.row.age}岁` : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #default="scope">
|
||||
{{ scope.row.age ? `${scope.row.age}岁` : '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="requestTime" align="center" label="申请时间" />
|
||||
<el-table-column prop="sourceName" align="center" label="申请来源" />
|
||||
<el-table-column prop="wardName" align="center" label="入院病区" />
|
||||
<el-table-column fixed="right" align="center" label="操作" width="88">
|
||||
<el-table-column fixed="right" align="center" label="操作" width="120">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="doRegistering(scope.row)"> 登记 </el-button>
|
||||
<el-button type="primary" link @click.stop="doRegistering(scope.row)"> 登记 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -68,10 +68,11 @@
|
||||
<script setup>
|
||||
import PatientRegister from './patientRegister.vue';
|
||||
import {getAdmissionPage, getInHospitalInfo, getPatientBasicInfo} from './api';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const emits = defineEmits(['okList']);
|
||||
|
||||
const total = ref();
|
||||
const total = ref(0);
|
||||
const patient = ref({});
|
||||
const inHospitalInfo = ref({});
|
||||
const noFile = ref(false);
|
||||
@@ -79,34 +80,84 @@ const registrationType = ref(true);
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined,
|
||||
registeredFlag: '0',
|
||||
searchKey: '',
|
||||
registeredFlag: '0',
|
||||
});
|
||||
|
||||
const treatHospitalizedData = ref([]);
|
||||
const doRegistering = (row) => {
|
||||
if (row == 'no-file') {
|
||||
patientRegisterVisible.value = true;
|
||||
noFile.value = true;
|
||||
inHospitalInfo.value = {};
|
||||
} else {
|
||||
getPatientBasicInfo(row.patientId).then((res) => {
|
||||
patient.value = res.data;
|
||||
});
|
||||
getInHospitalInfo(row.encounterId).then((res) => {
|
||||
inHospitalInfo.value = res.data;
|
||||
const patientRegisterVisible = ref(false);
|
||||
|
||||
// 修改后的 doRegistering 函数
|
||||
const doRegistering = async (row) => {
|
||||
|
||||
try {
|
||||
// 区分 'no-file' 字符串和对象
|
||||
if (typeof row === 'string' && row === 'no-file') {
|
||||
patientRegisterVisible.value = true;
|
||||
noFile.value = true;
|
||||
inHospitalInfo.value = {};
|
||||
patient.value = {};
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保 row 是对象且包含必要属性
|
||||
if (!row || typeof row !== 'object') {
|
||||
|
||||
ElMessage.error('无效的行数据');
|
||||
return;
|
||||
}
|
||||
|
||||
const { patientId, encounterId } = row;
|
||||
|
||||
// 检查必要字段是否存在
|
||||
if (patientId === undefined || patientId === null || patientId === '') {
|
||||
|
||||
ElMessage.error('患者 ID 不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
if (encounterId === undefined || encounterId === null || encounterId === '') {
|
||||
|
||||
ElMessage.error('就诊 ID 不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取患者基本信息
|
||||
|
||||
const patientRes = await getPatientBasicInfo(patientId);
|
||||
|
||||
if (patientRes.data) {
|
||||
patient.value = patientRes.data;
|
||||
} else {
|
||||
|
||||
ElMessage.warning('未获取到患者信息');
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取住院信息
|
||||
|
||||
const inHospitalRes = await getInHospitalInfo(encounterId);
|
||||
|
||||
if (inHospitalRes.code === 200 && inHospitalRes.data) {
|
||||
inHospitalInfo.value = inHospitalRes.data;
|
||||
patientRegisterVisible.value = true;
|
||||
noFile.value = false;
|
||||
});
|
||||
ElMessage.success('加载成功');
|
||||
} else {
|
||||
|
||||
ElMessage.error(inHospitalRes.msg || '未获取到住院信息');
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
ElMessage.error('登记失败:' + (error.message || '未知错误'));
|
||||
}
|
||||
};
|
||||
|
||||
const getList = () => {
|
||||
getAdmissionPage(queryParams.value).then((res) => {
|
||||
treatHospitalizedData.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
});
|
||||
treatHospitalizedData.value = res.data?.records || [];
|
||||
total.value = res.data?.total || 0;
|
||||
}).catch(err => console.error('获取列表失败', err));
|
||||
};
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
@@ -119,14 +170,11 @@ function resetQuery() {
|
||||
queryParams.value = {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined,
|
||||
registeredFlag: '0',
|
||||
searchKey: '',
|
||||
registeredFlag: '0',
|
||||
};
|
||||
getList();
|
||||
}
|
||||
const patientRegisterVisible = ref(false);
|
||||
const patientYbRegisterVisible = ref(false);
|
||||
|
||||
const patientRegisterOK = () => {
|
||||
patientRegisterVisible.value = false;
|
||||
@@ -136,10 +184,10 @@ const patientRegisterOK = () => {
|
||||
};
|
||||
|
||||
const cancelAct = () => {
|
||||
getList();
|
||||
patientRegisterVisible.value = false;
|
||||
};
|
||||
|
||||
// 页面加载时获取数据
|
||||
getList();
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -202,7 +202,7 @@
|
||||
<script setup>
|
||||
import {
|
||||
diagnosisInit,
|
||||
getAllWards,
|
||||
getPractitionerWard,
|
||||
getBedInfo,
|
||||
getContractList,
|
||||
getDiagnosisDefinitionList,
|
||||
@@ -427,13 +427,13 @@ function getInitOptions() {
|
||||
// 获取所有科室
|
||||
const orgPromise = getOrgList();
|
||||
// 获取所有病区
|
||||
const wardPromise = getAllWards();
|
||||
const wardPromise = getPractitionerWard();
|
||||
|
||||
Promise.all([orgPromise, wardPromise]).then(([orgRes, wardRes]) => {
|
||||
const allOrgs = orgRes.data.records.filter(
|
||||
(record) => record.typeEnum === 2 && checkClassEnumValue(record.classEnum, 2)
|
||||
);
|
||||
const allWards = wardRes.data.records || [];
|
||||
const allWards = wardRes.data || [];
|
||||
|
||||
// 提取所有病区关联的科室ID
|
||||
const linkedOrgIds = new Set();
|
||||
|
||||
@@ -189,6 +189,7 @@ import {patientInfo} from '../../store/patient.js';
|
||||
import {ElMessage} from 'element-plus';
|
||||
// const diagnosisList = ref([]);
|
||||
const allowAdd = ref(false);
|
||||
const isSaving = ref(false);
|
||||
const tree = ref([]);
|
||||
const openDiagnosis = ref(false);
|
||||
const openAddDiagnosisDialog = ref(false);
|
||||
@@ -229,15 +230,42 @@ watch(
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
// 监听患者信息变化,自动获取病历详情和诊断列表
|
||||
watch(
|
||||
() => props.patientInfo,
|
||||
(newVal) => {
|
||||
if (newVal?.encounterId) {
|
||||
getDetail(newVal.encounterId);
|
||||
getList();
|
||||
}
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
|
||||
function getDetail(encounterId) {
|
||||
if (!encounterId) {
|
||||
console.warn('未提供有效的就诊ID,无法获取病历详情');
|
||||
allowAdd.value = false;
|
||||
return;
|
||||
}
|
||||
|
||||
getEmrDetail(encounterId).then((res) => {
|
||||
allowAdd.value = res.data ? true : false;
|
||||
});
|
||||
console.log('正在获取病历详情,encounterId:', encounterId);
|
||||
|
||||
getEmrDetail(encounterId)
|
||||
.then((res) => {
|
||||
console.log('病历详情API返回:', res);
|
||||
if (res.code === 200) {
|
||||
allowAdd.value = res.data ? true : false;
|
||||
console.log('设置 allowAdd =', allowAdd.value, ', 病历数据:', res.data);
|
||||
} else {
|
||||
allowAdd.value = false;
|
||||
console.warn('获取病历详情失败:', res.msg);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('获取病历详情异常:', error);
|
||||
allowAdd.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
function getList() {
|
||||
@@ -246,6 +274,9 @@ function getList() {
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化中医诊断列表
|
||||
const newList = [];
|
||||
|
||||
getEncounterDiagnosis(props.patientInfo.encounterId).then((res) => {
|
||||
if (res.code == 200) {
|
||||
const datas = (res.data || []).map((item) => {
|
||||
@@ -405,30 +436,57 @@ function getTree() {
|
||||
* 添加西医诊断
|
||||
*/
|
||||
function handleAddDiagnosis() {
|
||||
proxy.$refs.formRef.validate((valid) => {
|
||||
console.log('点击新增诊断按钮,allowAdd:', allowAdd.value);
|
||||
|
||||
// 检查表单ref是否存在
|
||||
if (!proxy.$refs.formRef) {
|
||||
console.error('表单ref不存在');
|
||||
// 直接添加诊断,不经过表单验证
|
||||
addDiagnosisItem();
|
||||
return;
|
||||
}
|
||||
|
||||
proxy.$refs.formRef.validate((valid, fields) => {
|
||||
console.log('表单验证结果:', valid, '错误字段:', fields);
|
||||
if (valid) {
|
||||
if (!allowAdd.value) {
|
||||
proxy.$modal.msgWarning('请先填写病历');
|
||||
return;
|
||||
}
|
||||
form.value.diagnosisList.push({
|
||||
showPopover: false,
|
||||
name: undefined,
|
||||
verificationStatusEnum: 4,
|
||||
medTypeCode: undefined, // 不设默认值
|
||||
diagSrtNo: form.value.diagnosisList.length + 1,
|
||||
iptDiseTypeCode: 2,
|
||||
diagnosisDesc: '',
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN')
|
||||
});
|
||||
if (form.value.diagnosisList.length == 1) {
|
||||
form.value.diagnosisList[0].maindiseFlag = 1;
|
||||
addDiagnosisItem();
|
||||
} else {
|
||||
console.warn('表单验证失败:', fields);
|
||||
// 验证失败时也允许添加(因为是新增空行)
|
||||
if (allowAdd.value) {
|
||||
console.log('验证失败但允许添加,强制添加诊断');
|
||||
addDiagnosisItem();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加诊断项
|
||||
*/
|
||||
function addDiagnosisItem() {
|
||||
console.log('执行添加诊断,当前列表长度:', form.value.diagnosisList.length);
|
||||
form.value.diagnosisList.push({
|
||||
showPopover: false,
|
||||
name: undefined,
|
||||
verificationStatusEnum: 4,
|
||||
medTypeCode: undefined,
|
||||
diagSrtNo: form.value.diagnosisList.length + 1,
|
||||
iptDiseTypeCode: 2,
|
||||
diagnosisDesc: '',
|
||||
diagnosisDoctor: props.patientInfo.practitionerName || props.patientInfo.doctorName || props.patientInfo.physicianName || userStore.name,
|
||||
diagnosisTime: new Date().toLocaleString('zh-CN')
|
||||
});
|
||||
if (form.value.diagnosisList.length == 1) {
|
||||
form.value.diagnosisList[0].maindiseFlag = 1;
|
||||
}
|
||||
console.log('添加完成,新列表长度:', form.value.diagnosisList.length);
|
||||
}
|
||||
|
||||
// 添加中医诊断
|
||||
function handleAddTcmDiagonsis() {
|
||||
openAddDiagnosisDialog.value = true;
|
||||
|
||||
@@ -541,11 +541,14 @@ function getListInfo(addNewRow) {
|
||||
loadingInstance.close();
|
||||
prescriptionList.value = res.data
|
||||
.map((item) => {
|
||||
const parsedContent = JSON.parse(item.contentJson);
|
||||
return {
|
||||
...JSON.parse(item.contentJson),
|
||||
...parsedContent,
|
||||
...item,
|
||||
doseQuantity: JSON.parse(item.contentJson)?.doseQuantity,
|
||||
doseUnitCode_dictText: JSON.parse(item.contentJson)?.doseUnitCode_dictText,
|
||||
doseQuantity: parsedContent?.doseQuantity,
|
||||
doseUnitCode_dictText: parsedContent?.doseUnitCode_dictText,
|
||||
// 确保 therapyEnum 被正确设置,优先使用 contentJson 中的值
|
||||
therapyEnum: String(parsedContent?.therapyEnum ?? item.therapyEnum ?? '1'),
|
||||
};
|
||||
})
|
||||
.sort((a, b) => {
|
||||
@@ -604,7 +607,7 @@ function handleAddPrescription() {
|
||||
showPopover: false,
|
||||
isEdit: true,
|
||||
statusEnum: 1,
|
||||
therapyEnum: '1',
|
||||
therapyEnum: '1', // 默认为长期医嘱
|
||||
});
|
||||
getGroupMarkers();
|
||||
nextTick(() => {
|
||||
@@ -641,8 +644,8 @@ function clickRowDb(row, column, event) {
|
||||
}
|
||||
row.showPopover = false;
|
||||
if (row.statusEnum == 1) {
|
||||
// 确保治疗类型为字符串,方便与单选框 label 对齐
|
||||
row.therapyEnum = String(row.therapyEnum ?? '');
|
||||
// 确保治疗类型为字符串,方便与单选框 label 对齐,默认为长期医嘱('1')
|
||||
row.therapyEnum = String(row.therapyEnum ?? '1');
|
||||
row.isEdit = true;
|
||||
const index = prescriptionList.value.findIndex((item) => item.uniqueKey === row.uniqueKey);
|
||||
prescriptionList.value[index] = row;
|
||||
@@ -879,13 +882,16 @@ function handleSave() {
|
||||
// 此处签发处方和单行保存处方传参相同,后台已经将传参存为JSON字符串,此处直接转换为JSON即可
|
||||
loading.value = true;
|
||||
let list = saveList.map((item) => {
|
||||
const parsedContent = JSON.parse(item.contentJson);
|
||||
return {
|
||||
...JSON.parse(item.contentJson),
|
||||
...parsedContent,
|
||||
adviceType: item.adviceType,
|
||||
requestId: item.requestId,
|
||||
dbOpType: '1',
|
||||
groupId: item.groupId,
|
||||
uniqueKey: undefined,
|
||||
// 确保 therapyEnum 被正确传递
|
||||
therapyEnum: parsedContent.therapyEnum || item.therapyEnum || '1',
|
||||
};
|
||||
});
|
||||
// 保存签发按钮
|
||||
@@ -1059,6 +1065,8 @@ function handleSaveSign(row, index) {
|
||||
row.conditionDefinitionId = conditionDefinitionId.value;
|
||||
row.encounterDiagnosisId = encounterDiagnosisId.value;
|
||||
row.diagnosisName = diagnosisName.value;
|
||||
// 确保 therapyEnum 被正确设置,默认为长期医嘱('1')
|
||||
row.therapyEnum = row.therapyEnum || '1';
|
||||
if (row.injectFlag == 1) {
|
||||
row.sortNumber = row.sortNumber ? row.sortNumber : prescriptionList.value.length;
|
||||
}
|
||||
@@ -1098,8 +1106,11 @@ function handleSaveBatch() {
|
||||
return item.statusEnum == 1 && !item.requestId;
|
||||
})
|
||||
.map((item) => {
|
||||
// 确保 therapyEnum 被正确传递,默认为长期医嘱('1')
|
||||
const therapyEnum = item.therapyEnum || '1';
|
||||
return {
|
||||
...item,
|
||||
therapyEnum: therapyEnum,
|
||||
dbOpType: item.requestId ? '2' : '1',
|
||||
};
|
||||
});
|
||||
@@ -1246,6 +1257,8 @@ function handleSaveGroup(orderGroupList) {
|
||||
conditionId: conditionId.value, // 诊断id
|
||||
conditionDefinitionId: conditionDefinitionId.value, // 诊断定义id
|
||||
encounterDiagnosisId: encounterDiagnosisId.value, // 就诊诊断id
|
||||
// 确保 therapyEnum 被正确设置,默认为长期医嘱('1')
|
||||
therapyEnum: prescriptionList.value[rowIndex.value]?.therapyEnum || '1',
|
||||
};
|
||||
|
||||
// 计算价格和总量
|
||||
@@ -1278,7 +1291,12 @@ function handleSaveHistory(value) {
|
||||
conditionId: conditionId.value,
|
||||
conditionDefinitionId: conditionDefinitionId.value,
|
||||
encounterDiagnosisId: encounterDiagnosisId.value,
|
||||
contentJson: JSON.stringify(value),
|
||||
// 确保 therapyEnum 被正确传递,默认为长期医嘱('1')
|
||||
therapyEnum: value.therapyEnum || '1',
|
||||
contentJson: JSON.stringify({
|
||||
...value,
|
||||
therapyEnum: value.therapyEnum || '1',
|
||||
}),
|
||||
};
|
||||
savePrescription({ adviceSaveList: [saveRow], regAdviceSaveList: [saveRow] }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
|
||||
@@ -137,6 +137,7 @@ const queryParams = ref({
|
||||
name: '',
|
||||
useRanges: [1, 2], // 0 暂不使用 1 全院 2 科室 3 个人
|
||||
organizationId: userStore.orgId,
|
||||
primaryMenuEnum: 1, // 1-住院病历 (DocTypeEnum.IN_DOC)
|
||||
});
|
||||
const loading = ref(false); // 数据加载状态
|
||||
const currentSelectTemplate = ref({
|
||||
@@ -560,12 +561,12 @@ const loadLatestMedicalRecord = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
// 获取患者的历史病历记录
|
||||
// const res = await getRecordByEncounterIdList({
|
||||
// isPage: 0,
|
||||
// encounterId: patientInfo.value.encounterId,
|
||||
// patientId: patientInfo.value.patientId,
|
||||
// definitionId: currentSelectTemplate.value.id,
|
||||
// });
|
||||
const res = await getRecordByEncounterIdList({
|
||||
isPage: 0,
|
||||
encounterId: patientInfo.value.encounterId,
|
||||
patientId: patientInfo.value.patientId,
|
||||
definitionId: currentSelectTemplate.value.id,
|
||||
});
|
||||
|
||||
const historyRecords = res.data || [];
|
||||
if (historyRecords.length > 0) {
|
||||
@@ -623,7 +624,8 @@ const loadLatestMedicalRecord = async () => {
|
||||
loading.value = false;
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error('加载最新病历数据失败=====>', error);
|
||||
console.error('加载最新病历数据失败:', error);
|
||||
ElMessage.error('加载最新病历数据失败');
|
||||
// 出错时也清空选中状态
|
||||
selectedHistoryRecordId.value = '';
|
||||
// 出错时也要清空表单数据,避免显示之前患者的数据
|
||||
|
||||
@@ -153,6 +153,7 @@ const handleItemClick = (node) => {
|
||||
updateLocalPatientInfo(node);
|
||||
|
||||
diagnosisRef.value?.getList();
|
||||
diagnosisRef.value?.getDetail(node?.encounterId);
|
||||
adviceRef.value?.getListInfo();
|
||||
adviceRef.value?.getDiagnosisInfo();
|
||||
}, 100); // 100ms 防抖延迟
|
||||
@@ -189,6 +190,7 @@ watch(activeTabName, (newTab) => {
|
||||
provide('diagnosisInit', (value) => {
|
||||
currentPatientInfo.value = value;
|
||||
diagnosisRef.value.getList();
|
||||
diagnosisRef.value.getDetail(value?.encounterId);
|
||||
});
|
||||
provide('getAdviceList', (value) => {
|
||||
adviceRef.value.getListInfo();
|
||||
|
||||
@@ -107,6 +107,7 @@ import PatientList from '../components/patientList.vue';
|
||||
import PrescriptionList from './components/prescriptionList.vue';
|
||||
import SummaryMedicineList from './components/summaryMedicineList.vue';
|
||||
import {inpatientNurseNavs} from '../constants/navigation';
|
||||
import { RequestStatus } from '@/utils/medicalConstants';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const router = useRouter();
|
||||
@@ -115,7 +116,7 @@ const activeName = ref('preparation');
|
||||
const active = ref('first');
|
||||
const exeStatus = ref(1);
|
||||
const deadline = ref(proxy.formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
|
||||
const requestStatus = ref(3);
|
||||
const requestStatus = ref(RequestStatus.COMPLETED);
|
||||
const chooseAll = ref(false);
|
||||
const drugType = ref('1');
|
||||
const isDetails = ref('1');
|
||||
|
||||
@@ -26,14 +26,12 @@
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="" prop="checkboxGroup2">
|
||||
<el-form-item label="" prop="nursingLevelList">
|
||||
<el-checkbox-group v-model="queryParams.nursingLevelList" @change="getList">
|
||||
<el-checkbox-button
|
||||
v-for="item in levelList"
|
||||
:key="item.value"
|
||||
v-model="item.value"
|
||||
style="display: inline-block"
|
||||
:label="item.label"
|
||||
:label="item.value"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-checkbox-button>
|
||||
@@ -187,7 +185,7 @@ const data = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined, // 品名/商品名/英文品名/编码/拼音
|
||||
checkboxGroup2: [], // 类型(包括 1:中药,2:成药)
|
||||
nursingLevelList: [], // 护理级别列表(多选)
|
||||
statusEnum: 1, // 状态
|
||||
},
|
||||
rules: {},
|
||||
|
||||
@@ -89,7 +89,7 @@ import Filter from '@/components/TableLayout/Filter.vue';
|
||||
import {computed, onBeforeMount, onMounted, reactive, ref} from 'vue';
|
||||
import TransferInDialog from './transferInDialog.vue';
|
||||
import SignEntryDialog from './signEntryDialog.vue';
|
||||
import {childLocationList, getBedInfo, getInit, getPendingInfo, getWardList} from './api';
|
||||
import {childLocationList, getBedInfo, getInit, getPendingInfo, getPractitionerWard} from './api';
|
||||
import {ElLoading, ElMessage, ElMessageBox} from 'element-plus';
|
||||
import PendingPatientList from '@/components/PendingPatientList/index.vue';
|
||||
|
||||
@@ -233,8 +233,8 @@ const ininData = async () => {
|
||||
priorityOptions.value = initRes.data.priorityOptions || [];
|
||||
|
||||
// 然后获取病区数据(使用与病区管理页面相同的接口)
|
||||
const wardRes = await getWardList({ pageNum: 1, pageSize: 50, formEnum: 4 });
|
||||
const wardList = wardRes.data?.records || [];
|
||||
const wardRes = await getPractitionerWard();
|
||||
const wardList = wardRes.data || [];
|
||||
selectHosLoding.value = false;
|
||||
queryParams.value.wardId = wardList[0]?.id || '';
|
||||
initInfoOptions.value.wardListOptions = wardList;
|
||||
|
||||
@@ -389,52 +389,77 @@ const interventionForm = ref({
|
||||
startTime: '', //入院时间
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.pendingInfo,
|
||||
(newVal, oldVal) => {
|
||||
console.log(newVal);
|
||||
if (newVal) {
|
||||
getPatientInfo({ encounterId: newVal.encounterId }).then((res) => {
|
||||
console.log('res============>', JSON.stringify(res.data));
|
||||
|
||||
pendingInfo.value = res.data;
|
||||
interventionForm.value.admittingDoctorId = res.data.admittingDoctorId;
|
||||
interventionForm.value.attendingDoctorId = res.data.attendingDoctorId;
|
||||
if (res.data.chiefDoctorId) {
|
||||
interventionForm.value.chiefDoctorId = res.data.chiefDoctorId;
|
||||
}
|
||||
interventionForm.value.primaryNurseId = res.data.primaryNurseId;
|
||||
if (res.data.startTime) {
|
||||
interventionForm.value.startTime = dayjs(res.data.startTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss'
|
||||
);
|
||||
} else {
|
||||
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
interventionForm.value.height = res.data.height;
|
||||
interventionForm.value.weight = res.data.weight;
|
||||
interventionForm.value.temperature = res.data.temperature;
|
||||
interventionForm.value.hertRate = res.data.hertRate;
|
||||
interventionForm.value.pulse = res.data.pulse;
|
||||
interventionForm.value.endBloodPressure = res.data.endBloodPressure;
|
||||
interventionForm.value.highBloodPressure = res.data.highBloodPressure;
|
||||
});
|
||||
interventionForm.value.priorityEnum = newVal.priorityEnum;
|
||||
interventionForm.value.organizationName = newVal.organizationName;
|
||||
interventionForm.value.wardName = newVal.wardName;
|
||||
interventionForm.value.bedName = newVal.bedName;
|
||||
/**
|
||||
* 获取患者详细信息并填充表单
|
||||
*/
|
||||
const loadPatientInfo = () => {
|
||||
if (!props.pendingInfo?.encounterId) {
|
||||
return;
|
||||
}
|
||||
console.log('查询患者信息的 encounterId:', props.pendingInfo.encounterId);
|
||||
getPatientInfo({ encounterId: props.pendingInfo.encounterId }).then((res) => {
|
||||
console.log('后端返回的患者信息:', res.data);
|
||||
pendingInfo.value = res.data;
|
||||
// 从后端获取数据后设置医生和护士 ID
|
||||
// 医生使用 ToStringSerializer,返回字符串;护士直接返回数字
|
||||
console.log('admittingDoctorId:', res.data.admittingDoctorId);
|
||||
console.log('attendingDoctorId:', res.data.attendingDoctorId);
|
||||
console.log('chiefDoctorId:', res.data.chiefDoctorId);
|
||||
console.log('primaryNurseId:', res.data.primaryNurseId);
|
||||
if (res.data.admittingDoctorId) {
|
||||
interventionForm.value.admittingDoctorId = String(res.data.admittingDoctorId);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
if (res.data.attendingDoctorId) {
|
||||
interventionForm.value.attendingDoctorId = String(res.data.attendingDoctorId);
|
||||
}
|
||||
if (res.data.chiefDoctorId) {
|
||||
interventionForm.value.chiefDoctorId = String(res.data.chiefDoctorId);
|
||||
}
|
||||
if (res.data.primaryNurseId) {
|
||||
// 护士ID也转换为字符串以匹配护士选项
|
||||
interventionForm.value.primaryNurseId = String(res.data.primaryNurseId);
|
||||
}
|
||||
if (res.data.startTime) {
|
||||
interventionForm.value.startTime = dayjs(res.data.startTime).format(
|
||||
'YYYY-MM-DD HH:mm:ss'
|
||||
);
|
||||
} else {
|
||||
interventionForm.value.startTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
interventionForm.value.height = res.data.height;
|
||||
interventionForm.value.weight = res.data.weight;
|
||||
interventionForm.value.temperature = res.data.temperature;
|
||||
interventionForm.value.hertRate = res.data.hertRate;
|
||||
interventionForm.value.pulse = res.data.pulse;
|
||||
interventionForm.value.endBloodPressure = res.data.endBloodPressure;
|
||||
interventionForm.value.highBloodPressure = res.data.highBloodPressure;
|
||||
});
|
||||
interventionForm.value.priorityEnum = props.pendingInfo.priorityEnum || '';
|
||||
interventionForm.value.organizationName = props.pendingInfo.organizationName || '';
|
||||
interventionForm.value.wardName = props.pendingInfo.wardName || '';
|
||||
interventionForm.value.bedName = props.pendingInfo.bedName || '';
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.pendingInfo?.encounterId,
|
||||
(newVal, oldVal) => {
|
||||
// encounterId 存在时就获取数据
|
||||
if (newVal) {
|
||||
console.log('watch 触发, newVal:', newVal, 'oldVal:', oldVal);
|
||||
loadPatientInfo();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/* 初始化数据 */
|
||||
const init = () => {
|
||||
initCurrentInPatient();
|
||||
getInit()
|
||||
|
||||
const promises = [];
|
||||
|
||||
const initPromise = getInit()
|
||||
.then((res) => {
|
||||
InitInfoOptions.value = res.data;
|
||||
// 安全地设置priorityListOptions
|
||||
if (res.data && res.data.priorityListOptions) {
|
||||
priorityListOptions.value = res.data.priorityListOptions;
|
||||
}
|
||||
@@ -442,9 +467,10 @@ const init = () => {
|
||||
.catch((error) => {
|
||||
console.error('获取初始化数据失败:', error);
|
||||
});
|
||||
promises.push(initPromise);
|
||||
|
||||
if (props.pendingInfo.wardLocationId) {
|
||||
getBedInfo({ wardLocationId: props.pendingInfo.wardLocationId })
|
||||
const bedPromise = getBedInfo({ wardLocationId: props.pendingInfo.wardLocationId })
|
||||
.then((res) => {
|
||||
bedInfoOptions.value = res.data || [];
|
||||
})
|
||||
@@ -452,52 +478,62 @@ const init = () => {
|
||||
console.error('获取床位信息失败:', error);
|
||||
bedInfoOptions.value = [];
|
||||
});
|
||||
promises.push(bedPromise);
|
||||
}
|
||||
|
||||
if (props.pendingInfo.organizationId) {
|
||||
// 主任医生
|
||||
getDoctorInfo({ organizationId: props.pendingInfo.organizationId })
|
||||
const doctorPromise = getDoctorInfo({ organizationId: props.pendingInfo.organizationId })
|
||||
.then((res) => {
|
||||
console.log('doctorInfoOptions======>', JSON.stringify(res.data));
|
||||
|
||||
doctorInfoOptions.value = res.data.records || [];
|
||||
nextTick(() => {
|
||||
// 如果存在主任医师显示主任,如果没有选择第一个展示
|
||||
if (doctorInfoOptions.value.length > 0) {
|
||||
let selectId = '';
|
||||
doctorInfoOptions.value.forEach((item: any) => {
|
||||
if (item.drProfttlCode == '231') {
|
||||
selectId = item.id;
|
||||
// 只有在新分配床位模式(entranceType != 1)时才设置默认主任医生
|
||||
// 并且只在当前没有选择主任医生时才设置默认值(避免覆盖已从后端获取的数据)
|
||||
if (props.pendingInfo.entranceType != 1) {
|
||||
nextTick(() => {
|
||||
if (doctorInfoOptions.value.length > 0 && !interventionForm.value.chiefDoctorId) {
|
||||
let selectId = '';
|
||||
doctorInfoOptions.value.forEach((item: any) => {
|
||||
if (item.drProfttlCode == '231') {
|
||||
selectId = item.id;
|
||||
}
|
||||
});
|
||||
if (selectId.length > 0) {
|
||||
interventionForm.value.chiefDoctorId = selectId;
|
||||
} else {
|
||||
interventionForm.value.chiefDoctorId = doctorInfoOptions.value[0].id;
|
||||
}
|
||||
});
|
||||
if (selectId.length > 0) {
|
||||
interventionForm.value.chiefDoctorId = selectId;
|
||||
} else {
|
||||
interventionForm.value.chiefDoctorId = doctorInfoOptions.value[0].id;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('获取医生信息失败:', error);
|
||||
doctorInfoOptions.value = [];
|
||||
});
|
||||
promises.push(doctorPromise);
|
||||
|
||||
getNurseInfo({ organizationId: props.pendingInfo.organizationId })
|
||||
const nursePromise = getNurseInfo({ organizationId: props.pendingInfo.organizationId })
|
||||
.then((res) => {
|
||||
nurseInfoOptions.value = res.data || [];
|
||||
// 将护士ID转换为字符串以匹配医生选项的数据类型
|
||||
nurseInfoOptions.value = (res.data || []).map((item: any) => ({
|
||||
...item,
|
||||
practitionerId: String(item.practitionerId),
|
||||
}));
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('获取护士信息失败:', error);
|
||||
nurseInfoOptions.value = [];
|
||||
});
|
||||
promises.push(nursePromise);
|
||||
}
|
||||
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
const rules = reactive<FormRules>({
|
||||
admittingDoctorId: [{ required: true, message: '请选择住院医生', trigger: ['blur', 'change'] }],
|
||||
primaryNurseId: [{ required: true, message: '请选择责任护士', trigger: ['blur', 'change'] }],
|
||||
bedLocationId: [{ required: true, message: '请选择入住床位', trigger: ['blur', 'change'] }],
|
||||
// 主治医生和主任医生为可选字段,不添加 required 验证
|
||||
});
|
||||
|
||||
const printWristband = ref(false);
|
||||
@@ -512,29 +548,10 @@ const cancelAct = () => {
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
// interventionForm.value = {
|
||||
// height: undefined,
|
||||
// weight: undefined,
|
||||
// temperature: undefined,
|
||||
// hertRate: undefined,
|
||||
// pulse: undefined,
|
||||
// endBloodPressure: undefined,
|
||||
// highBloodPressure: undefined,
|
||||
// bedLocationId: '', // 床号
|
||||
// admittingDoctorId: '', // 住院医师
|
||||
// attendingDoctorId: '', // 主治医师
|
||||
// chiefDoctorId: '', // 主任医师
|
||||
// primaryNurseId: '', // 责任护士
|
||||
// priorityEnum: '', //患者病情
|
||||
// organizationName: '',
|
||||
// wardName: '',
|
||||
// attendingDocUpdateId: '',
|
||||
// startTime: '', //入院时间
|
||||
// }
|
||||
|
||||
// 可选:清空校验状态
|
||||
// 只重置表单验证状态,不清空数据
|
||||
// 数据会在下次打开对话框时通过 loadPatientInfo 重新加载
|
||||
if (interventionFormRef.value) {
|
||||
interventionFormRef.value.resetFields();
|
||||
interventionFormRef.value.clearValidate();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -549,16 +566,27 @@ const handleSubmit = async () => {
|
||||
try {
|
||||
const valid = await interventionFormRef.value.validate();
|
||||
if (valid) {
|
||||
// 过滤掉空字符串的字段,只保留用户实际选择的值
|
||||
const formData = {};
|
||||
Object.keys(interventionForm.value).forEach(key => {
|
||||
const value = interventionForm.value[key];
|
||||
// 保留非空的值(0、false等有效值也需要保留)
|
||||
if (value !== '' && value !== null && value !== undefined) {
|
||||
formData[key] = value;
|
||||
}
|
||||
});
|
||||
const params = {
|
||||
...pendingInfo.value,
|
||||
...interventionForm.value,
|
||||
...formData,
|
||||
targetBedId: props.pendingInfo.bedId,
|
||||
busNo: props.pendingInfo.busNo,
|
||||
inHosTime: props.pendingInfo.inHosTime,
|
||||
targetHouseId: props.pendingInfo.targetHouseId,
|
||||
targetEncounterId: props.pendingInfo.targetEncounterId,
|
||||
editFlag: props.pendingInfo.entranceType == 1 ? 1 : 0,
|
||||
editFlag: props.pendingInfo.entranceType == 1 ? '1' : '0',
|
||||
};
|
||||
console.log('提交参数:', params);
|
||||
console.log('startTime:', interventionForm.value.startTime);
|
||||
|
||||
bedAssignment(params)
|
||||
.then((res: any) => {
|
||||
@@ -583,19 +611,15 @@ const handleSubmit = async () => {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('表单验证失败:', error);
|
||||
console.error('表单验证失败:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const openAct = () => {
|
||||
init();
|
||||
if (props.pendingInfo) {
|
||||
interventionForm.value.priorityEnum = props.pendingInfo.priorityEnum || '';
|
||||
interventionForm.value.admittingDoctorId = props.pendingInfo.practitionerId || '';
|
||||
interventionForm.value.organizationName = props.pendingInfo.organizationName || '';
|
||||
interventionForm.value.wardName = props.pendingInfo.wardName || '';
|
||||
interventionForm.value.attendingDocUpdateId = props.pendingInfo.admittingDoctorId || '';
|
||||
}
|
||||
// 先初始化数据(包括医生护士列表),等待完成后再加载患者信息
|
||||
init().then(() => {
|
||||
loadPatientInfo();
|
||||
});
|
||||
};
|
||||
|
||||
const closedAct = () => {
|
||||
|
||||
@@ -54,11 +54,12 @@
|
||||
import {getCurrentInstance} from 'vue';
|
||||
import PatientList from '../components/patientList.vue';
|
||||
import PrescriptionList from './components/prescriptionList.vue';
|
||||
import { RequestStatus } from '@/utils/medicalConstants';
|
||||
|
||||
const activeName = ref('preparation');
|
||||
const active = ref('first');
|
||||
const exeStatus = ref(1);
|
||||
const requestStatus = ref(3);
|
||||
const requestStatus = ref(RequestStatus.COMPLETED);
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
// 存储子组件引用的对象
|
||||
|
||||
@@ -52,10 +52,11 @@
|
||||
<script setup>
|
||||
import PatientList from '../components/patientList.vue';
|
||||
import PrescriptionList from './components/prescriptionList.vue';
|
||||
import { RequestStatus } from '@/utils/medicalConstants';
|
||||
|
||||
const activeName = ref('unverified');
|
||||
const active = ref('first');
|
||||
const requestStatus = ref(2);
|
||||
const requestStatus = ref(RequestStatus.ACTIVE);
|
||||
|
||||
// 存储子组件引用的对象
|
||||
const prescriptionRefs = ref({});
|
||||
|
||||
@@ -136,7 +136,7 @@ const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined,
|
||||
orgId: userStore.orgId,
|
||||
orgId: userStore.orgId, // 按当前用户科室过滤
|
||||
});
|
||||
|
||||
const recordQueryParams = ref({
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -112,16 +112,16 @@
|
||||
<select v-model="item.type" :class="{ 'placeholder-text': !item.type }">
|
||||
<option value="">选择检查类型</option>
|
||||
<option
|
||||
v-for="dict in inspectionTypeDicts"
|
||||
:key="dict.dictValue"
|
||||
:value="dict.dictValue"
|
||||
v-for="opt in checkTypeOptions"
|
||||
:key="opt.value"
|
||||
:value="opt.value"
|
||||
>
|
||||
{{ dict.dictLabel }}
|
||||
{{ opt.label }}
|
||||
</option>
|
||||
</select>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span v-if="item.type">{{ getInspectionTypeLabel(item.type) }}</span>
|
||||
<span v-if="item.type">{{ getCheckTypeLabel(item.type) }}</span>
|
||||
<span v-else class="placeholder-text">选择检查类型</span>
|
||||
</template>
|
||||
</td>
|
||||
@@ -219,10 +219,10 @@
|
||||
<label>检查类型</label>
|
||||
<el-select v-model="searchParamsMethod.checkType" placeholder="选择检查类型" style="width: 150px">
|
||||
<el-option
|
||||
v-for="dict in inspectionTypeDicts"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
v-for="item in checkTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
@@ -237,8 +237,8 @@
|
||||
<el-option
|
||||
v-for="pkg in checkPackages"
|
||||
:key="pkg.id"
|
||||
:label="pkg.name"
|
||||
:value="pkg.name"
|
||||
:label="pkg.packageName"
|
||||
:value="pkg.packageName"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
@@ -293,25 +293,37 @@
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<select v-model="item.checkType">
|
||||
<option value="">选择检查类型</option>
|
||||
<option
|
||||
v-for="dict in inspectionTypeDicts"
|
||||
:key="dict.dictValue"
|
||||
:value="dict.dictValue"
|
||||
>
|
||||
{{ dict.dictLabel }}
|
||||
</option>
|
||||
</select>
|
||||
<el-select v-model="item.checkType" placeholder="选择检查类型" style="width: 100%">
|
||||
<el-option
|
||||
v-for="opt in checkTypeOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ getInspectionTypeLabel(item.checkType) || '无' }}
|
||||
{{ getCheckTypeLabel(item.checkType) || '无' }}
|
||||
</template>
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<input type="text" placeholder="请输入套餐名称" v-model="item.packageName">
|
||||
<el-select
|
||||
v-model="item.packageName"
|
||||
placeholder="请选择套餐"
|
||||
style="width: 100%"
|
||||
filterable
|
||||
clearable
|
||||
:filter-method="filterPackageOptions"
|
||||
>
|
||||
<el-option
|
||||
v-for="pkg in filteredPackageOptions"
|
||||
:key="pkg.id"
|
||||
:label="pkg.packageName"
|
||||
:value="pkg.packageName"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.packageName || '' }}
|
||||
@@ -378,10 +390,10 @@
|
||||
<label>检查类型</label>
|
||||
<el-select v-model="searchParamsPart.checkType" placeholder="选择检查类型" style="width: 150px">
|
||||
<el-option
|
||||
v-for="dict in inspectionTypeDicts"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
v-for="item in checkTypeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
@@ -392,7 +404,21 @@
|
||||
</div>
|
||||
<div class="search-item">
|
||||
<label>费用套餐</label>
|
||||
<el-input placeholder="费用套餐" v-model="searchParamsPart.packageName" />
|
||||
<el-select
|
||||
v-model="searchParamsPart.packageName"
|
||||
placeholder="选择套餐"
|
||||
style="width: 150px"
|
||||
filterable
|
||||
clearable
|
||||
:filter-method="filterPackageOptions"
|
||||
>
|
||||
<el-option
|
||||
v-for="pkg in filteredPackageOptions"
|
||||
:key="pkg.id"
|
||||
:label="pkg.packageName"
|
||||
:value="pkg.packageName"
|
||||
/>
|
||||
</el-select>
|
||||
</div>
|
||||
|
||||
<div class="search-actions">
|
||||
@@ -447,19 +473,17 @@
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<select v-model="item.checkType">
|
||||
<option value="">选择检查类型</option>
|
||||
<option
|
||||
v-for="dict in inspectionTypeDicts"
|
||||
:key="dict.dictValue"
|
||||
:value="dict.dictValue"
|
||||
>
|
||||
{{ dict.dictLabel }}
|
||||
</option>
|
||||
</select>
|
||||
<el-select v-model="item.checkType" placeholder="选择检查类型" style="width: 100%">
|
||||
<el-option
|
||||
v-for="opt in checkTypeOptions"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ getInspectionTypeLabel(item.checkType) || '无' }}
|
||||
{{ getCheckTypeLabel(item.checkType) || '无' }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
@@ -472,12 +496,34 @@
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<input type="text" placeholder="请输入费用套餐" v-model="item.packageName">
|
||||
<el-select
|
||||
v-model="item.packageName"
|
||||
placeholder="请选择套餐"
|
||||
style="width: 100%"
|
||||
filterable
|
||||
clearable
|
||||
:filter-method="filterPackageOptions"
|
||||
>
|
||||
<el-option
|
||||
v-for="pkg in filteredPackageOptions"
|
||||
:key="pkg.id"
|
||||
:label="pkg.packageName"
|
||||
:value="pkg.packageName"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.packageName || '' }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<input type="number" min="0" placeholder="请输入曝光次数" v-model="item.exposureNum">
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ item.exposureNum || '0' }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<input type="number" step="0.01" min="0" placeholder="请输入金额" v-model="item.price">
|
||||
@@ -496,19 +542,17 @@
|
||||
</td>
|
||||
<td>
|
||||
<template v-if="item.editing">
|
||||
<select v-model="item.serviceScope">
|
||||
<option value="">选择服务范围</option>
|
||||
<option
|
||||
<el-select v-model="item.serviceScope" placeholder="选择服务范围" style="width: 100%">
|
||||
<el-option
|
||||
v-for="dict in serviceScopeDicts"
|
||||
:key="dict.dictValue"
|
||||
:label="dict.dictLabel"
|
||||
:value="dict.dictValue"
|
||||
>
|
||||
{{ dict.dictLabel }}
|
||||
</option>
|
||||
</select>
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ getServiceScopeLabel(item.serviceScope) || '' }}
|
||||
{{ getServiceScopeLabel(item.serviceScope) || '无' }}
|
||||
</template>
|
||||
</td>
|
||||
<td>
|
||||
@@ -596,6 +640,7 @@ import {
|
||||
delCheckType,
|
||||
exportCheckMethod,
|
||||
exportCheckPart,
|
||||
getAllCheckTypes,
|
||||
listCheckMethod,
|
||||
listCheckPackage,
|
||||
listCheckPart,
|
||||
@@ -622,6 +667,8 @@ const currentPackageData = ref(null)
|
||||
|
||||
// 检查类型和科室选项
|
||||
const checkTypes = ref([]);
|
||||
// 从检查类型维护界面获取的检查类型列表(用于下拉选项)
|
||||
const checkTypeOptions = ref([]);
|
||||
// 完整的检查类型字典数据
|
||||
const inspectionTypeDicts = ref([]);
|
||||
// 完整的服务范围字典数据
|
||||
@@ -634,6 +681,13 @@ const checkTypes = ref([]);
|
||||
return dictItem ? dictItem.dictLabel : value;
|
||||
};
|
||||
|
||||
// 根据值从检查类型选项中获取标签
|
||||
const getCheckTypeLabel = (value) => {
|
||||
if (!value) return '';
|
||||
const option = checkTypeOptions.value.find(item => item.value === value);
|
||||
return option ? option.label : value;
|
||||
};
|
||||
|
||||
// 根据字典值获取服务范围标签
|
||||
const getServiceScopeLabel = (value) => {
|
||||
const dictItem = serviceScopeDicts.value.find(item => item.dictValue === value);
|
||||
@@ -641,8 +695,21 @@ const checkTypes = ref([]);
|
||||
};
|
||||
const checkParts = ref([]);
|
||||
const checkPackages = ref([]);
|
||||
// 套餐下拉选项的过滤结果
|
||||
const filteredPackageOptions = ref([]);
|
||||
const departments = ref([]);
|
||||
|
||||
// 套餐模糊查询过滤方法
|
||||
const filterPackageOptions = (query) => {
|
||||
if (query) {
|
||||
filteredPackageOptions.value = checkPackages.value.filter(pkg =>
|
||||
pkg.packageName && pkg.packageName.toLowerCase().includes(query.toLowerCase())
|
||||
);
|
||||
} else {
|
||||
filteredPackageOptions.value = checkPackages.value;
|
||||
}
|
||||
};
|
||||
|
||||
// 表格数据 - 为每个菜单创建独立的数据存储
|
||||
const checkTypeData = reactive([]);
|
||||
const checkMethodData = reactive([]);
|
||||
@@ -813,20 +880,18 @@ onMounted(async () => {
|
||||
inspectionTypeDicts.value = typeResponse.data;
|
||||
// 从数据字典获取检查类型值
|
||||
checkTypes.value = typeResponse.data.map(item => item.dictValue);
|
||||
// 从数据字典获取检查类型下拉选项
|
||||
checkTypeOptions.value = typeResponse.data.map(item => ({
|
||||
value: item.dictValue,
|
||||
label: item.dictLabel,
|
||||
dictValue: item.dictValue,
|
||||
dictLabel: item.dictLabel
|
||||
}));
|
||||
} else {
|
||||
checkTypes.value = [];
|
||||
inspectionTypeDicts.value = [];
|
||||
}
|
||||
|
||||
// 获取服务范围数据(从数据字典获取)
|
||||
const scopeResponse = await getDicts('scope_of_services');
|
||||
if (scopeResponse && scopeResponse.data) {
|
||||
// 保存完整的服务范围字典数据
|
||||
serviceScopeDicts.value = scopeResponse.data;
|
||||
} else {
|
||||
serviceScopeDicts.value = [];
|
||||
}
|
||||
|
||||
// 获取检查类型表格数据(分页获取)
|
||||
await loadCheckTypeDataWithPagination();
|
||||
|
||||
@@ -853,8 +918,11 @@ onMounted(async () => {
|
||||
if (packageResponse && packageResponse.data) {
|
||||
// 确保data是数组类型
|
||||
checkPackages.value = Array.isArray(packageResponse.data) ? packageResponse.data : [];
|
||||
// 初始化过滤后的套餐选项
|
||||
filteredPackageOptions.value = checkPackages.value;
|
||||
} else {
|
||||
checkPackages.value = [];
|
||||
filteredPackageOptions.value = [];
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
@@ -1161,13 +1229,29 @@ async function handleConfirm(index) {
|
||||
ElMessage.error('名称不能为空');
|
||||
return;
|
||||
}
|
||||
if (!item.type || item.type.trim() === '') {
|
||||
ElMessage.error('检查类型不能为空');
|
||||
return;
|
||||
// 根据不同菜单验证检查类型字段
|
||||
if (activeMenu.value === '检查方法') {
|
||||
if (!item.checkType || item.checkType.trim() === '') {
|
||||
ElMessage.error('检查类型不能为空');
|
||||
return;
|
||||
}
|
||||
} else if (activeMenu.value === '检查类型') {
|
||||
if (!item.type || item.type.trim() === '') {
|
||||
ElMessage.error('检查类型不能为空');
|
||||
return;
|
||||
}
|
||||
} else if (activeMenu.value === '检查部位') {
|
||||
if (!item.checkType || item.checkType.trim() === '') {
|
||||
ElMessage.error('检查类型不能为空');
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!item.department || item.department.trim() === '') {
|
||||
ElMessage.error('执行科室不能为空');
|
||||
return;
|
||||
// 检查类型才需要验证执行科室
|
||||
if (activeMenu.value === '检查类型') {
|
||||
if (!item.department || item.department.trim() === '') {
|
||||
ElMessage.error('执行科室不能为空');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -516,6 +516,7 @@ import {
|
||||
getPharmacyList,
|
||||
getTransferProductDetail,
|
||||
getTransferProductDetails,
|
||||
getWarehouseList,
|
||||
productTransferApproved,
|
||||
reject,
|
||||
submitApproval,
|
||||
@@ -775,6 +776,17 @@ function handleChangePurposeTypeEnum(value, type) {
|
||||
}).catch(error => {
|
||||
console.error('Error fetching dispensary list:', error);
|
||||
});
|
||||
} else if (value == 17) {
|
||||
// 耗材库类型
|
||||
getWarehouseList().then((res) => {
|
||||
purposeTypeListOptions.value = res.data;
|
||||
if (!route.query.supplyBusNo && !type) {
|
||||
receiptHeaderForm.purposeLocationId = '';
|
||||
receiptHeaderForm.purposeLocationId1 = '';
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error fetching warehouse list:', error);
|
||||
});
|
||||
} else {
|
||||
purposeTypeListOptions.value = [];
|
||||
}
|
||||
@@ -801,6 +813,17 @@ function handleChangeSourceTypeEnum(value, type) {
|
||||
}).catch(error => {
|
||||
console.error('Error fetching dispensary list:', error);
|
||||
});
|
||||
} else if (value == 17) {
|
||||
// 耗材库类型
|
||||
getWarehouseList().then((res) => {
|
||||
sourceTypeListOptions.value = res.data;
|
||||
if (!route.query.supplyBusNo && !type) {
|
||||
receiptHeaderForm.sourceLocationId = '';
|
||||
receiptHeaderForm.sourceLocationId1 = '';
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Error fetching warehouse list:', error);
|
||||
});
|
||||
} else {
|
||||
sourceTypeListOptions.value = [];
|
||||
}
|
||||
|
||||
@@ -123,6 +123,14 @@ export function getDispensaryList() {
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
// 获取耗材库列表
|
||||
export function getWarehouseList() {
|
||||
return request({
|
||||
url: '/app-common/warehouse-list',
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
// 获取仓库药房列表
|
||||
export function getpharmacyCabinetList() {
|
||||
return request({
|
||||
|
||||
@@ -616,6 +616,7 @@ import {
|
||||
getInit,
|
||||
getPharmacyList,
|
||||
getTransferProductDetail,
|
||||
getWarehouseList,
|
||||
productTransferApproved,
|
||||
reject,
|
||||
submitApproval,
|
||||
@@ -1148,6 +1149,15 @@ function handleChangePurposeTypeEnum(value, type) {
|
||||
receiptHeaderForm.purposeLocationId1 = '';
|
||||
}
|
||||
});
|
||||
} else if (value == 17) {
|
||||
// 耗材库类型
|
||||
getWarehouseList().then((res) => {
|
||||
purposeTypeListOptions.value = res.data;
|
||||
if (!route.query.supplyBusNo && !type) {
|
||||
receiptHeaderForm.purposeLocationId = '';
|
||||
receiptHeaderForm.purposeLocationId1 = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,6 +1179,15 @@ function handleChangeSourceTypeEnum(value, type) {
|
||||
receiptHeaderForm.sourceLocationId1 = '';
|
||||
}
|
||||
});
|
||||
} else if (value == 17) {
|
||||
// 耗材库类型
|
||||
getWarehouseList().then((res) => {
|
||||
sourceTypeListOptions.value = res.data;
|
||||
if (!route.query.supplyBusNo && !type) {
|
||||
receiptHeaderForm.sourceLocationId = '';
|
||||
receiptHeaderForm.sourceLocationId1 = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
<el-table-column type="selection" width="55" align="center" fixed="left"/>
|
||||
<el-table-column prop="prescriptionNo" label="处方号" width="120" align="center"/>
|
||||
<el-table-column prop="conditionName" label="诊断" width="120" align="center"/>
|
||||
<el-table-column prop="medTypeCode_dictText" label="处方类型" width="120" align="center"/>
|
||||
<el-table-column prop="dispenseEnum_enumText" label="处方类型" width="120" align="center"/>
|
||||
<el-table-column prop="itemName" label="项目名称" width="160" align="center"/>
|
||||
<el-table-column prop="merchandiseName" label="商品名称" width="160" align="center"/>
|
||||
<el-table-column prop="quantity" label="发药数量" width="130" align="center">
|
||||
@@ -836,7 +836,7 @@ function getRowMarkers(groupCounts, data) {
|
||||
|
||||
function spanMethod({row, column, rowIndex, columnIndex}) {
|
||||
// 定义需要合并的列范围(前6列,包括selection列)
|
||||
const columnsToMerge = [1, 2, 3, 17]; // 假设selection列是第0列,其他列依次是1, 2, 3, 4, 5
|
||||
const columnsToMerge = [1, 2, 3]; // 假设selection列是第0列,其他列依次是1, 2, 3, 4, 5
|
||||
// 检查当前列是否在需要合并的列范围内
|
||||
if (row.prescriptionNo) {
|
||||
if (columnsToMerge.includes(columnIndex)) {
|
||||
|
||||
16
sql/20260311_add_diagnosis_date_fields.sql
Normal file
16
sql/20260311_add_diagnosis_date_fields.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- 为 adm_encounter_diagnosis 表添加发病日期和诊断日期字段
|
||||
-- 执行日期: 2026-03-11
|
||||
-- 问题: 诊断保存后发病日期和诊断日期不显示
|
||||
-- 原因: 数据库表缺少这两个字段
|
||||
|
||||
-- 添加发病日期字段
|
||||
ALTER TABLE public.adm_encounter_diagnosis
|
||||
ADD COLUMN IF NOT EXISTS onset_date date;
|
||||
|
||||
COMMENT ON COLUMN public.adm_encounter_diagnosis.onset_date IS '发病日期';
|
||||
|
||||
-- 添加诊断日期字段
|
||||
ALTER TABLE public.adm_encounter_diagnosis
|
||||
ADD COLUMN IF NOT EXISTS diagnosis_time date;
|
||||
|
||||
COMMENT ON COLUMN public.adm_encounter_diagnosis.diagnosis_time IS '诊断日期';
|
||||
62
sql/create_lab_observation_table.sql
Normal file
62
sql/create_lab_observation_table.sql
Normal file
@@ -0,0 +1,62 @@
|
||||
-- =============================================
|
||||
-- 创建 lab_observation 表
|
||||
-- 用途: 实验室观察记录表
|
||||
-- 创建时间: 2026-03-09
|
||||
-- =============================================
|
||||
|
||||
-- 删除已存在的表(如果存在)
|
||||
DROP TABLE IF EXISTS lab_observation;
|
||||
|
||||
-- 创建序列(如果不存在)
|
||||
DROP SEQUENCE IF EXISTS lab_observation_id_seq;
|
||||
CREATE SEQUENCE lab_observation_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
-- 创建表
|
||||
CREATE TABLE lab_observation (
|
||||
id BIGINT PRIMARY KEY DEFAULT nextval('lab_observation_id_seq'),
|
||||
patient_id BIGINT,
|
||||
encounter_id BIGINT,
|
||||
specimen_id BIGINT,
|
||||
observation_definition_id BIGINT,
|
||||
observation_result TEXT,
|
||||
observation_date TIMESTAMP,
|
||||
technician_id BIGINT,
|
||||
delete_flag VARCHAR(1) DEFAULT '0',
|
||||
create_by VARCHAR(64) DEFAULT '',
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_by VARCHAR(64) DEFAULT '',
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
remark VARCHAR(500)
|
||||
);
|
||||
|
||||
-- 添加表注释
|
||||
COMMENT ON TABLE lab_observation IS '实验室观察记录表';
|
||||
|
||||
-- 添加字段注释
|
||||
COMMENT ON COLUMN lab_observation.id IS '观察记录的唯一标识符';
|
||||
COMMENT ON COLUMN lab_observation.patient_id IS '患者ID';
|
||||
COMMENT ON COLUMN lab_observation.encounter_id IS '就诊ID';
|
||||
COMMENT ON COLUMN lab_observation.specimen_id IS '关联的样本ID';
|
||||
COMMENT ON COLUMN lab_observation.observation_definition_id IS '观察定义ID';
|
||||
COMMENT ON COLUMN lab_observation.observation_result IS '观察结果,可能是文本描述或数值';
|
||||
COMMENT ON COLUMN lab_observation.observation_date IS '观察的日期和时间';
|
||||
COMMENT ON COLUMN lab_observation.technician_id IS '执行观察的技术员ID';
|
||||
COMMENT ON COLUMN lab_observation.delete_flag IS '删除状态,0-未删除,1-已删除';
|
||||
COMMENT ON COLUMN lab_observation.create_by IS '创建者';
|
||||
COMMENT ON COLUMN lab_observation.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN lab_observation.update_by IS '更新者';
|
||||
COMMENT ON COLUMN lab_observation.update_time IS '更新时间';
|
||||
COMMENT ON COLUMN lab_observation.remark IS '备注';
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX idx_lab_observation_patient_id ON lab_observation(patient_id);
|
||||
CREATE INDEX idx_lab_observation_specimen_id ON lab_observation(specimen_id);
|
||||
CREATE INDEX idx_lab_observation_observation_date ON lab_observation(observation_date);
|
||||
|
||||
-- 打印完成信息
|
||||
SELECT 'lab_observation 表创建成功!' AS message;
|
||||
86
sql/create_lab_specimen_tables.sql
Normal file
86
sql/create_lab_specimen_tables.sql
Normal file
@@ -0,0 +1,86 @@
|
||||
-- 创建 lab_specimen 检验标本表
|
||||
CREATE TABLE hisdev.lab_specimen (
|
||||
id BIGINT NOT NULL,
|
||||
service_id BIGINT,
|
||||
tenant_id BIGINT,
|
||||
specimen_definition_id BIGINT,
|
||||
collection_status_enum INTEGER,
|
||||
collection_date TIMESTAMP WITHOUT TIME ZONE,
|
||||
received_date TIMESTAMP WITHOUT TIME ZONE,
|
||||
specimen_volume VARCHAR(50),
|
||||
specimen_unit VARCHAR(20),
|
||||
create_by VARCHAR(50),
|
||||
create_time TIMESTAMP WITHOUT TIME ZONE,
|
||||
update_by VARCHAR(50),
|
||||
update_time TIMESTAMP WITH TIME ZONE,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE hisdev.lab_specimen IS '检验标本表';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.id IS '主键ID';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.service_id IS '服务请求ID(关联wor_service_request)';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.tenant_id IS '租户ID';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.specimen_definition_id IS '标本定义ID(关联adm_specimen_definition)';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.collection_status_enum IS '采集状态(1:待采集 2:已采集 3:已接收)';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.collection_date IS '采集时间';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.received_date IS '接收时间';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.specimen_volume IS '标本量';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.specimen_unit IS '标本单位';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.create_by IS '创建人';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.create_time IS '创建时间';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.update_by IS '更新人';
|
||||
COMMENT ON COLUMN hisdev.lab_specimen.update_time IS '更新时间';
|
||||
|
||||
-- 创建 adm_specimen_definition 标本定义表
|
||||
CREATE TABLE hisdev.adm_specimen_definition (
|
||||
id BIGINT NOT NULL,
|
||||
code VARCHAR(50),
|
||||
name VARCHAR(100),
|
||||
specimen_name VARCHAR(100),
|
||||
delete_flag CHAR(1) DEFAULT '0',
|
||||
create_by VARCHAR(50),
|
||||
create_time TIMESTAMP WITHOUT TIME ZONE,
|
||||
update_by VARCHAR(50),
|
||||
update_time TIMESTAMP WITH TIME ZONE,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE hisdev.adm_specimen_definition IS '标本定义表';
|
||||
COMMENT ON COLUMN hisdev.adm_specimen_definition.id IS '主键ID';
|
||||
COMMENT ON COLUMN hisdev.adm_specimen_definition.code IS '标本编码';
|
||||
COMMENT ON COLUMN hisdev.adm_specimen_definition.name IS '标本名称';
|
||||
COMMENT ON COLUMN hisdev.adm_specimen_definition.specimen_name IS '标本显示名称';
|
||||
COMMENT ON COLUMN hisdev.adm_specimen_definition.delete_flag IS '删除标志(0:正常 1:删除)';
|
||||
|
||||
-- 创建 adm_observation_definition 检验项目定义表
|
||||
CREATE TABLE hisdev.adm_observation_definition (
|
||||
id BIGINT NOT NULL,
|
||||
code VARCHAR(50),
|
||||
name VARCHAR(100),
|
||||
category VARCHAR(50),
|
||||
unit VARCHAR(20),
|
||||
reference_range VARCHAR(200),
|
||||
normal_range VARCHAR(200),
|
||||
delete_flag CHAR(1) DEFAULT '0',
|
||||
create_by VARCHAR(50),
|
||||
create_time TIMESTAMP WITHOUT TIME ZONE,
|
||||
update_by VARCHAR(50),
|
||||
update_time TIMESTAMP WITH TIME ZONE,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE hisdev.adm_observation_definition IS '检验项目定义表';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.id IS '主键ID';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.code IS '项目编码';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.name IS '项目名称';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.category IS '项目类别';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.unit IS '单位';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.reference_range IS '参考范围';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.normal_range IS '正常范围';
|
||||
COMMENT ON COLUMN hisdev.adm_observation_definition.delete_flag IS '删除标志(0:正常 1:删除)';
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX idx_lab_specimen_service_id ON hisdev.lab_specimen(service_id);
|
||||
CREATE INDEX idx_lab_specimen_specimen_def ON hisdev.lab_specimen(specimen_definition_id);
|
||||
CREATE INDEX idx_adm_specimen_definition_code ON hisdev.adm_specimen_definition(code);
|
||||
CREATE INDEX idx_adm_observation_definition_code ON hisdev.adm_observation_definition(code);
|
||||
327
sql/迁移记录-DB变更记录/202603051000_card_management_menu.sql
Normal file
327
sql/迁移记录-DB变更记录/202603051000_card_management_menu.sql
Normal file
@@ -0,0 +1,327 @@
|
||||
-- ============================================
|
||||
-- STORY #104: 增加报卡管理界面
|
||||
-- 创建时间: 2026-03-05
|
||||
-- 功能说明: 在疾病报告管理目录下增加报卡管理界面菜单
|
||||
-- ============================================
|
||||
|
||||
-- 1. 创建疾病报告管理目录(如果不存在)
|
||||
-- 注意:需要根据实际情况调整parent_id,这里假设是一级菜单
|
||||
INSERT INTO "sys_menu" (
|
||||
"menu_name",
|
||||
"parent_id",
|
||||
"order_num",
|
||||
"path",
|
||||
"component",
|
||||
"query",
|
||||
"route_name",
|
||||
"is_frame",
|
||||
"is_cache",
|
||||
"menu_type",
|
||||
"visible",
|
||||
"status",
|
||||
"perms",
|
||||
"icon",
|
||||
"create_by",
|
||||
"create_time",
|
||||
"update_by",
|
||||
"update_time",
|
||||
"remark"
|
||||
)
|
||||
SELECT
|
||||
'疾病报告管理',
|
||||
0, -- 一级菜单,根据实际情况调整
|
||||
100,
|
||||
'diseaseReport',
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
'1',
|
||||
'0',
|
||||
'M', -- M=目录
|
||||
'0',
|
||||
'0',
|
||||
NULL,
|
||||
'documentation',
|
||||
'admin',
|
||||
NOW(),
|
||||
NULL,
|
||||
NULL,
|
||||
'疾病报告管理目录'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_menu" WHERE "menu_name" = '疾病报告管理'
|
||||
);
|
||||
|
||||
-- 2. 创建报卡管理菜单
|
||||
-- 获取疾病报告管理目录的ID
|
||||
INSERT INTO "sys_menu" (
|
||||
"menu_name",
|
||||
"parent_id",
|
||||
"order_num",
|
||||
"path",
|
||||
"component",
|
||||
"query",
|
||||
"route_name",
|
||||
"is_frame",
|
||||
"is_cache",
|
||||
"menu_type",
|
||||
"visible",
|
||||
"status",
|
||||
"perms",
|
||||
"icon",
|
||||
"create_by",
|
||||
"create_time",
|
||||
"update_by",
|
||||
"update_time",
|
||||
"remark"
|
||||
)
|
||||
SELECT
|
||||
'报卡管理',
|
||||
(SELECT "menu_id" FROM "sys_menu" WHERE "menu_name" = '疾病报告管理' LIMIT 1),
|
||||
1,
|
||||
'cardManagement',
|
||||
'cardmanagement/index',
|
||||
NULL,
|
||||
'CardManagement',
|
||||
'1',
|
||||
'0',
|
||||
'C', -- C=菜单
|
||||
'0',
|
||||
'0',
|
||||
'card:management:list',
|
||||
'form',
|
||||
'admin',
|
||||
NOW(),
|
||||
NULL,
|
||||
NULL,
|
||||
'报卡管理界面'
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_menu" WHERE "menu_name" = '报卡管理'
|
||||
);
|
||||
|
||||
-- 3. 创建报卡管理相关按钮权限
|
||||
-- 获取报卡管理菜单的ID
|
||||
INSERT INTO "sys_menu" (
|
||||
"menu_name",
|
||||
"parent_id",
|
||||
"order_num",
|
||||
"path",
|
||||
"component",
|
||||
"query",
|
||||
"route_name",
|
||||
"is_frame",
|
||||
"is_cache",
|
||||
"menu_type",
|
||||
"visible",
|
||||
"status",
|
||||
"perms",
|
||||
"icon",
|
||||
"create_by",
|
||||
"create_time",
|
||||
"update_by",
|
||||
"update_time",
|
||||
"remark"
|
||||
)
|
||||
SELECT
|
||||
'报卡查询',
|
||||
(SELECT "menu_id" FROM "sys_menu" WHERE "menu_name" = '报卡管理' LIMIT 1),
|
||||
1,
|
||||
'',
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
'1',
|
||||
'0',
|
||||
'F', -- F=按钮
|
||||
'0',
|
||||
'0',
|
||||
'card:management:query',
|
||||
'#',
|
||||
'admin',
|
||||
NOW(),
|
||||
NULL,
|
||||
NULL,
|
||||
''
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_menu" WHERE "perms" = 'card:management:query'
|
||||
);
|
||||
|
||||
INSERT INTO "sys_menu" (
|
||||
"menu_name",
|
||||
"parent_id",
|
||||
"order_num",
|
||||
"path",
|
||||
"component",
|
||||
"query",
|
||||
"route_name",
|
||||
"is_frame",
|
||||
"is_cache",
|
||||
"menu_type",
|
||||
"visible",
|
||||
"status",
|
||||
"perms",
|
||||
"icon",
|
||||
"create_by",
|
||||
"create_time",
|
||||
"update_by",
|
||||
"update_time",
|
||||
"remark"
|
||||
)
|
||||
SELECT
|
||||
'报卡审核',
|
||||
(SELECT "menu_id" FROM "sys_menu" WHERE "menu_name" = '报卡管理' LIMIT 1),
|
||||
2,
|
||||
'',
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
'1',
|
||||
'0',
|
||||
'F',
|
||||
'0',
|
||||
'0',
|
||||
'card:management:audit',
|
||||
'#',
|
||||
'admin',
|
||||
NOW(),
|
||||
NULL,
|
||||
NULL,
|
||||
''
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_menu" WHERE "perms" = 'card:management:audit'
|
||||
);
|
||||
|
||||
INSERT INTO "sys_menu" (
|
||||
"menu_name",
|
||||
"parent_id",
|
||||
"order_num",
|
||||
"path",
|
||||
"component",
|
||||
"query",
|
||||
"route_name",
|
||||
"is_frame",
|
||||
"is_cache",
|
||||
"menu_type",
|
||||
"visible",
|
||||
"status",
|
||||
"perms",
|
||||
"icon",
|
||||
"create_by",
|
||||
"create_time",
|
||||
"update_by",
|
||||
"update_time",
|
||||
"remark"
|
||||
)
|
||||
SELECT
|
||||
'报卡导出',
|
||||
(SELECT "menu_id" FROM "sys_menu" WHERE "menu_name" = '报卡管理' LIMIT 1),
|
||||
3,
|
||||
'',
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
'1',
|
||||
'0',
|
||||
'F',
|
||||
'0',
|
||||
'0',
|
||||
'card:management:export',
|
||||
'#',
|
||||
'admin',
|
||||
NOW(),
|
||||
NULL,
|
||||
NULL,
|
||||
''
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM "sys_menu" WHERE "perms" = 'card:management:export'
|
||||
);
|
||||
|
||||
-- 4. 创建数据库表(如果不存在)
|
||||
-- 传染病报卡表
|
||||
CREATE TABLE IF NOT EXISTS "infectious_card" (
|
||||
"id" BIGINT PRIMARY KEY,
|
||||
"card_no" VARCHAR(20) UNIQUE,
|
||||
"visit_id" BIGINT,
|
||||
"diag_id" BIGINT,
|
||||
"pat_id" BIGINT,
|
||||
"id_type" INTEGER,
|
||||
"id_no" VARCHAR(30),
|
||||
"pat_name" VARCHAR(50),
|
||||
"parent_name" VARCHAR(50),
|
||||
"sex" CHAR(1),
|
||||
"birthday" DATE,
|
||||
"age" INTEGER,
|
||||
"age_unit" CHAR(1),
|
||||
"workplace" VARCHAR(100),
|
||||
"phone" VARCHAR(20),
|
||||
"contact_phone" VARCHAR(20),
|
||||
"address_prov" VARCHAR(50),
|
||||
"address_city" VARCHAR(50),
|
||||
"address_county" VARCHAR(50),
|
||||
"address_town" VARCHAR(50),
|
||||
"address_village" VARCHAR(80),
|
||||
"address_house" VARCHAR(40),
|
||||
"patientbelong" VARCHAR(20),
|
||||
"occupation" VARCHAR(20),
|
||||
"disease_code" VARCHAR(10),
|
||||
"disease_name" VARCHAR(100),
|
||||
"disease_subtype" VARCHAR(50),
|
||||
"other_disease" VARCHAR(100),
|
||||
"disease_type" CHAR(1),
|
||||
"onset_date" DATE,
|
||||
"diag_date" TIMESTAMP,
|
||||
"death_date" DATE,
|
||||
"revised_disease_name" VARCHAR(100),
|
||||
"return_reason" VARCHAR(200),
|
||||
"report_org" VARCHAR(100),
|
||||
"report_org_phone" VARCHAR(20),
|
||||
"report_doc" VARCHAR(50),
|
||||
"report_date" DATE,
|
||||
"status" CHAR(1) DEFAULT '0',
|
||||
"fail_msg" VARCHAR(500),
|
||||
"xml_content" TEXT,
|
||||
"card_name_code" INTEGER,
|
||||
"registration_source" INTEGER,
|
||||
"dept_id" BIGINT,
|
||||
"dept_name" VARCHAR(100),
|
||||
"doctor_id" BIGINT,
|
||||
"create_by" VARCHAR(64),
|
||||
"create_time" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
"update_by" VARCHAR(64),
|
||||
"update_time" TIMESTAMP,
|
||||
"remark" VARCHAR(500)
|
||||
);
|
||||
|
||||
-- 审核记录表
|
||||
CREATE TABLE IF NOT EXISTS "infectious_audit" (
|
||||
"audit_id" BIGINT PRIMARY KEY,
|
||||
"card_id" BIGINT NOT NULL,
|
||||
"audit_seq" INTEGER NOT NULL,
|
||||
"audit_type" CHAR(1) NOT NULL,
|
||||
"audit_status_from" CHAR(1) NOT NULL,
|
||||
"audit_status_to" CHAR(1) NOT NULL,
|
||||
"audit_time" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"auditor_id" VARCHAR(20) NOT NULL,
|
||||
"auditor_name" VARCHAR(50) NOT NULL,
|
||||
"audit_opinion" TEXT,
|
||||
"reason_for_return" TEXT,
|
||||
"fail_reason_code" VARCHAR(20),
|
||||
"fail_reason_desc" TEXT,
|
||||
"is_batch" BOOLEAN DEFAULT FALSE,
|
||||
"batch_size" INTEGER DEFAULT 1,
|
||||
"create_by" VARCHAR(64),
|
||||
"create_time" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
"update_by" VARCHAR(64),
|
||||
"update_time" TIMESTAMP,
|
||||
"remark" VARCHAR(500)
|
||||
);
|
||||
|
||||
-- 创建索引
|
||||
CREATE INDEX IF NOT EXISTS idx_infectious_card_no ON "infectious_card"("card_no");
|
||||
CREATE INDEX IF NOT EXISTS idx_infectious_card_status ON "infectious_card"("status");
|
||||
CREATE INDEX IF NOT EXISTS idx_infectious_card_create_time ON "infectious_card"("create_time");
|
||||
CREATE INDEX IF NOT EXISTS idx_infectious_audit_card_id ON "infectious_audit"("card_id");
|
||||
|
||||
-- 添加迁移记录
|
||||
INSERT INTO __MigrationsHistory (MigrationId, ProductVersion)
|
||||
VALUES ('202603051000_card_management_menu', '1.0.0')
|
||||
ON CONFLICT DO NOTHING;
|
||||
Reference in New Issue
Block a user