Compare commits
18 Commits
5f134945ab
...
develop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16f6fbb8cf | ||
| 28f85ceb05 | |||
|
|
b43688e483 | ||
|
|
0bf29a53a4 | ||
|
|
0c70b224f9 | ||
|
|
449209a79b | ||
|
|
d6663c9667 | ||
|
|
53d29cbe14 | ||
|
|
e16a70dd50 | ||
|
|
bba63d2f1b | ||
|
|
f3d011951b | ||
| 7dc76d7b59 | |||
| b2dec2667a | |||
|
|
879d31b51d | ||
|
|
473a5f7f06 | ||
| 2eec988c56 | |||
| 8820048d55 | |||
| 6af7720470 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -353,8 +353,6 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
|
||||
encounterDiagnosis.setLongTermFlag(saveDiagnosisChildParam.getLongTermFlag());
|
||||
encounterDiagnosis.setOnsetDate(saveDiagnosisChildParam.getOnsetDate());
|
||||
encounterDiagnosis.setDiagnosisTime(saveDiagnosisChildParam.getDiagnosisTime());
|
||||
encounterDiagnosis.setOnsetDate(saveDiagnosisChildParam.getOnsetDate());
|
||||
encounterDiagnosis.setDiagnosisTime(saveDiagnosisChildParam.getDiagnosisTime());
|
||||
if(encounterDiagnosis.getCreateBy() == null){
|
||||
encounterDiagnosis.setCreateBy(username);
|
||||
}
|
||||
@@ -383,8 +381,6 @@ public class DoctorStationDiagnosisAppServiceImpl implements IDoctorStationDiagn
|
||||
encounterDiagnosis.setLongTermFlag(saveDiagnosisChildParam.getLongTermFlag());
|
||||
encounterDiagnosis.setOnsetDate(saveDiagnosisChildParam.getOnsetDate());
|
||||
encounterDiagnosis.setDiagnosisTime(saveDiagnosisChildParam.getDiagnosisTime());
|
||||
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,16 +133,35 @@ 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));
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存病历模板
|
||||
*
|
||||
|
||||
@@ -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 */
|
||||
@@ -256,4 +259,16 @@ public class AdviceSaveDto {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -95,6 +98,9 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
@Resource
|
||||
private IServiceRequestService serviceRequestService;
|
||||
|
||||
@Resource
|
||||
private IPractitionerService practitionerService;
|
||||
|
||||
/**
|
||||
* 入出转管理页面初始化
|
||||
*
|
||||
@@ -215,12 +221,131 @@ 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());
|
||||
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());
|
||||
}
|
||||
|
||||
// 查找各个角色 - 使用 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()));
|
||||
@@ -233,6 +358,13 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -288,6 +420,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> admissionBedAssignment(AdmissionPatientInfoDto admissionPatientInfoDto) {
|
||||
log.info("===== admissionBedAssignment 开始 =====");
|
||||
|
||||
// 住院id
|
||||
Long encounterId = admissionPatientInfoDto.getEncounterId();
|
||||
@@ -301,7 +434,10 @@ 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());
|
||||
@@ -329,6 +465,13 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
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);
|
||||
@@ -338,6 +481,11 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
return R.ok("患者信息更新成功");
|
||||
}
|
||||
|
||||
// 新分配床位时,校验床位信息
|
||||
if (targetBedId == null || admissionPatientInfoDto.getTargetHouseId() == null) {
|
||||
return R.fail("床位分配失败,请选择有效的床位");
|
||||
}
|
||||
|
||||
// 判断患者是否已经在床
|
||||
if (oldBedId != null) {
|
||||
// 判断目标床位是否已经被占用
|
||||
|
||||
@@ -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);
|
||||
List<EncounterDiagnosis> diagList;
|
||||
if (diagIdList.isEmpty()) {
|
||||
// 收费项未关联就诊诊断(如挂号费、自动诊疗费等),则直接从就诊维度查询诊断
|
||||
diagList = iEncounterDiagnosisService.getDiagnosisList(prePaymentDto.getEncounterId());
|
||||
if (diagList.isEmpty()) {
|
||||
throw new ServiceException("就诊诊断查询为空,错误信息:EncounterDiagnosis");
|
||||
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;
|
||||
if (chargeItem.getEncounterDiagnosisId() == null) {
|
||||
// 收费项未关联就诊诊断(如挂号费、自动诊疗费等),取诊断列表第一条作为兜底
|
||||
encounterDiagnosis = diagList.get(0);
|
||||
} else {
|
||||
Optional<EncounterDiagnosis> optional
|
||||
= diagList.stream().filter(e -> e.getId().equals(chargeItem.getEncounterDiagnosisId())).findFirst();
|
||||
|
||||
if (optional.isPresent()) {
|
||||
encounterDiagnosis = optional.get();
|
||||
} else {
|
||||
throw new ServiceException(
|
||||
"诊断信息与收费项的诊断信息未对应,错误信息:费用项" + chargeItem.getBusNo() + chargeItem.getEncounterDiagnosisId());
|
||||
// 收费项关联的诊断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;
|
||||
|
||||
/**
|
||||
* 查询住院患者信息
|
||||
*
|
||||
@@ -174,6 +183,9 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
||||
// 诊疗活动
|
||||
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)) {
|
||||
@@ -210,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集合
|
||||
@@ -594,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询住院医嘱请求数据
|
||||
*
|
||||
|
||||
@@ -55,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>
|
||||
|
||||
@@ -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,
|
||||
@@ -683,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>
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -290,46 +290,46 @@
|
||||
) AS ward ON ward.encounter_id = ae.id
|
||||
LEFT JOIN (
|
||||
SELECT aep.encounter_id,
|
||||
pra.id AS practitioner_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 = #{primaryNurse}
|
||||
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,
|
||||
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 = #{attendingDoctor}
|
||||
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,
|
||||
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 = #{admittingDoctor}
|
||||
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,
|
||||
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 = #{chiefDoctor}
|
||||
AND aep.type_code::text = CAST(#{chiefDoctor} AS TEXT)
|
||||
LIMIT 1
|
||||
) AS chiefDoctor ON chiefDoctor.encounter_id = ae.id
|
||||
LEFT JOIN adm_organization ao
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -59,6 +59,8 @@ 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)
|
||||
@@ -66,6 +68,7 @@ public class EncounterParticipantServiceImpl extends ServiceImpl<EncounterPartic
|
||||
.setTypeCode(typeCode)
|
||||
.setStatusEnum(EncounterActivityStatus.ACTIVE.getValue());
|
||||
int result = baseMapper.insert(encounterParticipant);
|
||||
log.info("创建参与者结果 - encounterId: {}, typeCode: {}, result: {}, insertId: {}", encounterId, typeCode, result, encounterParticipant.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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] || '未知状态';
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取诊断类型字典(异步初始化)
|
||||
*/
|
||||
|
||||
@@ -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 显示
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<el-input
|
||||
v-model="form.cardNo"
|
||||
class="card-number-input"
|
||||
placeholder="系统自动生成"
|
||||
disabled
|
||||
placeholder="单位自编,与网络直报一致"
|
||||
maxlength="12"
|
||||
/>
|
||||
</el-space>
|
||||
</el-card>
|
||||
@@ -32,7 +32,7 @@
|
||||
</el-col>
|
||||
<el-col :span="8" class="form-item">
|
||||
<span :class="['form-label', isChildPatient ? 'required' : '']">家长姓名</span>
|
||||
<el-input v-model="form.parentName" class="underline-input" :placeholder="isChildPatient ? '14岁以下必填' : ''" />
|
||||
<el-input v-model="form.parentName" class="underline-input" :placeholder="isChildPatient ? '≤14岁必填' : ''" />
|
||||
</el-col>
|
||||
<el-col :span="8" class="form-item">
|
||||
<span class="form-label required">身份证号</span>
|
||||
@@ -98,23 +98,29 @@
|
||||
<el-row :gutter="16" class="form-row">
|
||||
<el-col :span="24" class="form-item full-width">
|
||||
<span class="form-label required">现住地址</span>
|
||||
<div class="address-inputs region-selects-wrapper">
|
||||
<el-cascader
|
||||
v-model="addressCodes"
|
||||
:options="addressOptions"
|
||||
:props="addressCascaderProps"
|
||||
placeholder="请选择省/市/区县/街道"
|
||||
clearable
|
||||
@change="handleAddressChange"
|
||||
/>
|
||||
<div class="address-selects">
|
||||
<el-select v-model="provinceCode" placeholder="省" clearable @change="handleProvinceChange">
|
||||
<el-option v-for="item in provinceOptions" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
<el-select v-model="cityCode" placeholder="市" clearable @change="handleCityChange">
|
||||
<el-option v-for="item in cityOptions" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
<el-select v-model="countyCode" placeholder="区县" clearable @change="handleCountyChange">
|
||||
<el-option v-for="item in countyOptions" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="16" class="form-row">
|
||||
<el-col :span="12" class="form-item">
|
||||
<el-col :span="8" class="form-item">
|
||||
<el-select v-model="townCode" placeholder="街道" clearable @change="handleTownChange" class="underline-select">
|
||||
<el-option v-for="item in townOptions" :key="item.code" :label="item.name" :value="item.code" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
<el-col :span="8" class="form-item">
|
||||
<el-input v-model="form.addressVillage" class="underline-input" placeholder="村(居)" />
|
||||
</el-col>
|
||||
<el-col :span="12" class="form-item">
|
||||
<el-col :span="8" class="form-item">
|
||||
<el-input v-model="form.addressHouse" class="underline-input" placeholder="门牌号" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -135,26 +141,27 @@
|
||||
</el-row>
|
||||
|
||||
<!-- 职业 -->
|
||||
<!-- 职业、病例分类 -->
|
||||
<el-row :gutter="16" class="form-row">
|
||||
<el-col :span="24" class="form-item">
|
||||
<el-col :span="8" class="form-item">
|
||||
<span class="form-label required">职业</span>
|
||||
<el-select v-model="form.occupation" placeholder="请选择职业" class="full-select">
|
||||
<el-option v-for="item in occupationList" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 病例分类 -->
|
||||
<el-row :gutter="16" class="form-row">
|
||||
<el-col :span="24" class="form-item full-width">
|
||||
<el-col :span="16" class="form-item">
|
||||
<span class="form-label required">病例分类</span>
|
||||
<el-radio-group v-model="form.caseClass">
|
||||
<el-radio label="1">疑似病例</el-radio>
|
||||
<el-radio label="2">临床诊断病例</el-radio>
|
||||
<el-radio label="3">确诊病例</el-radio>
|
||||
<el-radio label="4">病原携带者</el-radio>
|
||||
<el-radio label="5">阳性检测结果</el-radio>
|
||||
</el-radio-group>
|
||||
<div class="case-class-group">
|
||||
<div class="case-class-row">
|
||||
<el-radio v-model="form.caseClass" label="1">疑似病例</el-radio>
|
||||
<el-radio v-model="form.caseClass" label="2">临床诊断病例</el-radio>
|
||||
<el-radio v-model="form.caseClass" label="3">确诊病例</el-radio>
|
||||
</div>
|
||||
<div class="case-class-row">
|
||||
<el-radio v-model="form.caseClass" label="4">病原携带者</el-radio>
|
||||
<el-radio v-model="form.caseClass" label="5">阳性检测结果(采供血机构填写)</el-radio>
|
||||
</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -327,7 +334,7 @@
|
||||
:model-value="form.selectedClassB === '0221'"
|
||||
@update:model-value="(checked) => handleClassBCheckbox('0221', checked)"
|
||||
label="0221"
|
||||
><EFBFBD><EFBFBD><EFBFBD><EFBFBD>病</el-checkbox>
|
||||
>淋病</el-checkbox>
|
||||
<el-checkbox
|
||||
:model-value="form.selectedClassB === '0222'"
|
||||
@update:model-value="(checked) => handleClassBCheckbox('0222', checked)"
|
||||
@@ -348,6 +355,21 @@
|
||||
@update:model-value="(checked) => handleClassBCheckbox('0225', checked)"
|
||||
label="0225"
|
||||
>疟疾</el-checkbox>
|
||||
<el-checkbox
|
||||
:model-value="form.selectedClassB === '0226'"
|
||||
@update:model-value="(checked) => handleClassBCheckbox('0226', checked)"
|
||||
label="0226"
|
||||
>新型冠状病毒肺炎</el-checkbox>
|
||||
<el-checkbox
|
||||
:model-value="form.selectedClassB === '0227'"
|
||||
@update:model-value="(checked) => handleClassBCheckbox('0227', checked)"
|
||||
label="0227"
|
||||
>甲型H1N1流感</el-checkbox>
|
||||
<el-checkbox
|
||||
:model-value="form.selectedClassB === '0228'"
|
||||
@update:model-value="(checked) => handleClassBCheckbox('0228', checked)"
|
||||
label="0228"
|
||||
>人感染H7N9禽流感</el-checkbox>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
@@ -404,7 +426,8 @@
|
||||
:model-value="form.selectedClassC === '0310'"
|
||||
@update:model-value="(checked) => handleClassCCheckbox('0310', checked)"
|
||||
label="0310"
|
||||
>其它感染性腹泻病</el-checkbox>
|
||||
class="wide-checkbox"
|
||||
>除霍乱/菌痢/伤寒副伤寒以外的感染性腹泻病</el-checkbox>
|
||||
<el-checkbox
|
||||
:model-value="form.selectedClassC === '0311'"
|
||||
@update:model-value="(checked) => handleClassCCheckbox('0311', checked)"
|
||||
@@ -495,7 +518,7 @@
|
||||
<script setup>
|
||||
import { ref, computed, getCurrentInstance, watch } from 'vue';
|
||||
import pcas from 'china-division/dist/pcas-code.json';
|
||||
import { saveInfectiousDiseaseReport, getNextCardNo } from '../api';
|
||||
import { saveInfectiousDiseaseReport } from '../api';
|
||||
import useUserStore from '@/store/modules/user';
|
||||
import { useDict } from '@/utils/dict';
|
||||
|
||||
@@ -543,17 +566,151 @@ const props = defineProps({
|
||||
const emit = defineEmits(['close', 'success']);
|
||||
|
||||
|
||||
// 地址级联选择器配置
|
||||
const addressOptions = ref(pcas);
|
||||
const addressCodes = ref([]);
|
||||
// 地址选择器数据
|
||||
const addressData = ref(pcas);
|
||||
const provinceCode = ref('');
|
||||
const cityCode = ref('');
|
||||
const countyCode = ref('');
|
||||
const townCode = ref('');
|
||||
const provinceOptions = ref([]);
|
||||
const cityOptions = ref([]);
|
||||
const countyOptions = ref([]);
|
||||
const townOptions = ref([]);
|
||||
|
||||
// 直辖市列表(这些城市的省级和市级相同)
|
||||
const municipalities = ['北京市', '天津市', '上海市', '重庆市'];
|
||||
const addressCascaderProps = {
|
||||
checkStrictly: true,
|
||||
value: 'code',
|
||||
label: 'name',
|
||||
children: 'children'
|
||||
};
|
||||
|
||||
// 初始化省级选项
|
||||
function initProvinceOptions() {
|
||||
provinceOptions.value = addressData.value.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
}));
|
||||
}
|
||||
|
||||
// 省级变化处理
|
||||
function handleProvinceChange(code) {
|
||||
cityCode.value = '';
|
||||
countyCode.value = '';
|
||||
townCode.value = '';
|
||||
cityOptions.value = [];
|
||||
countyOptions.value = [];
|
||||
townOptions.value = [];
|
||||
form.value.addressProv = '';
|
||||
form.value.addressCity = '';
|
||||
form.value.addressCounty = '';
|
||||
form.value.addressTown = '';
|
||||
|
||||
if (code) {
|
||||
const province = addressData.value.find(item => item.code === code);
|
||||
if (province) {
|
||||
form.value.addressProv = province.name;
|
||||
// 直辖市特殊处理:市级选项与省级相同
|
||||
if (municipalities.includes(province.name)) {
|
||||
cityOptions.value = [{ code: province.code, name: province.name }];
|
||||
cityCode.value = province.code;
|
||||
form.value.addressCity = province.name;
|
||||
// 直辖市的区县是省级的children
|
||||
if (province.children && province.children.length > 0) {
|
||||
countyOptions.value = province.children[0].children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
}
|
||||
} else {
|
||||
cityOptions.value = province.children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 市级变化处理
|
||||
function handleCityChange(code) {
|
||||
countyCode.value = '';
|
||||
townCode.value = '';
|
||||
countyOptions.value = [];
|
||||
townOptions.value = [];
|
||||
form.value.addressCity = '';
|
||||
form.value.addressCounty = '';
|
||||
form.value.addressTown = '';
|
||||
|
||||
if (code) {
|
||||
const province = addressData.value.find(item => item.code === provinceCode.value);
|
||||
if (province) {
|
||||
// 直辖市处理
|
||||
if (municipalities.includes(province.name)) {
|
||||
const county = province.children?.[0]?.children?.find(item => item.code === code);
|
||||
if (county) {
|
||||
form.value.addressCounty = county.name;
|
||||
townOptions.value = county.children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
}
|
||||
} else {
|
||||
const city = province.children?.find(item => item.code === code);
|
||||
if (city) {
|
||||
form.value.addressCity = city.name;
|
||||
countyOptions.value = city.children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 区县变化处理
|
||||
function handleCountyChange(code) {
|
||||
townCode.value = '';
|
||||
townOptions.value = [];
|
||||
form.value.addressCounty = '';
|
||||
form.value.addressTown = '';
|
||||
|
||||
if (code) {
|
||||
const province = addressData.value.find(item => item.code === provinceCode.value);
|
||||
if (province) {
|
||||
if (municipalities.includes(province.name)) {
|
||||
// 直辖市
|
||||
const county = province.children?.[0]?.children?.find(item => item.code === code);
|
||||
if (county) {
|
||||
form.value.addressCounty = county.name;
|
||||
townOptions.value = county.children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
}
|
||||
} else {
|
||||
const city = province.children?.find(item => item.code === cityCode.value);
|
||||
if (city) {
|
||||
const county = city.children?.find(item => item.code === code);
|
||||
if (county) {
|
||||
form.value.addressCounty = county.name;
|
||||
townOptions.value = county.children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 街道变化处理
|
||||
function handleTownChange(code) {
|
||||
form.value.addressTown = '';
|
||||
if (code) {
|
||||
const town = townOptions.value.find(item => item.code === code);
|
||||
if (town) {
|
||||
form.value.addressTown = town.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const form = ref({
|
||||
cardNo: '',
|
||||
@@ -601,65 +758,104 @@ const form = ref({
|
||||
diagnosisId: '',
|
||||
});
|
||||
|
||||
// 根据地址名称数组查找对应的代码数组(用于初始化地址选择器的回显)
|
||||
function findCodesByNames(names) {
|
||||
const codes = [];
|
||||
let currentNodes = addressOptions.value;
|
||||
// 根据地址名称初始化下拉选择器(用于回显)
|
||||
function initAddressByName(provName, cityName, countyName, townName) {
|
||||
if (!provName) return;
|
||||
|
||||
for (const name of names) {
|
||||
if (!name) break;
|
||||
const node = currentNodes?.find(n => n.name === name);
|
||||
if (node) {
|
||||
codes.push(node.code);
|
||||
currentNodes = node.children;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return codes;
|
||||
}
|
||||
// 初始化省级选项
|
||||
initProvinceOptions();
|
||||
|
||||
// 地址级联选择器变化处理
|
||||
function handleAddressChange(values) {
|
||||
if (!values || values.length === 0) {
|
||||
form.value.addressProv = '';
|
||||
form.value.addressCity = '';
|
||||
form.value.addressCounty = '';
|
||||
form.value.addressTown = '';
|
||||
return;
|
||||
}
|
||||
// 查找省份
|
||||
const province = addressData.value.find(item => item.name === provName);
|
||||
if (!province) return;
|
||||
|
||||
// 根据选中的代码获取对应的名称
|
||||
const names = [];
|
||||
let currentNodes = addressOptions.value;
|
||||
provinceCode.value = province.code;
|
||||
form.value.addressProv = province.name;
|
||||
|
||||
for (const code of values) {
|
||||
const node = currentNodes?.find(n => n.code === code);
|
||||
if (node) {
|
||||
names.push(node.name);
|
||||
currentNodes = node.children;
|
||||
}
|
||||
}
|
||||
|
||||
// 处理直辖市情况:如果是直辖市,市级和省级相同
|
||||
const provName = names[0] || '';
|
||||
let cityName = names[1] || '';
|
||||
const countyName = names[2] || '';
|
||||
const townName = names[3] || '';
|
||||
|
||||
// 如果是直辖市,市级应该与省级相同
|
||||
// 直辖市处理
|
||||
if (municipalities.includes(provName)) {
|
||||
// 直辖市:省级=市级
|
||||
form.value.addressProv = provName;
|
||||
form.value.addressCity = provName; // 直辖市的市级与省级相同
|
||||
form.value.addressCounty = cityName; // 原来的市级变成区县
|
||||
form.value.addressTown = countyName; // 原来的区县变成街道
|
||||
cityOptions.value = [{ code: province.code, name: province.name }];
|
||||
cityCode.value = province.code;
|
||||
form.value.addressCity = province.name;
|
||||
|
||||
// 直辖市的区县
|
||||
if (province.children && province.children.length > 0) {
|
||||
countyOptions.value = province.children[0].children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
|
||||
if (countyName) {
|
||||
const county = countyOptions.value.find(item => item.name === countyName);
|
||||
if (county) {
|
||||
countyCode.value = county.code;
|
||||
form.value.addressCounty = county.name;
|
||||
|
||||
// 获取原始区县数据以查找街道
|
||||
const countyData = province.children[0].children?.find(item => item.code === county.code);
|
||||
if (countyData && countyData.children) {
|
||||
townOptions.value = countyData.children.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
}));
|
||||
|
||||
if (townName) {
|
||||
const town = townOptions.value.find(item => item.name === townName);
|
||||
if (town) {
|
||||
townCode.value = town.code;
|
||||
form.value.addressTown = town.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 非直辖市:正常处理
|
||||
form.value.addressProv = provName;
|
||||
form.value.addressCity = cityName;
|
||||
form.value.addressCounty = countyName;
|
||||
form.value.addressTown = townName;
|
||||
// 非直辖市处理
|
||||
cityOptions.value = province.children?.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
})) || [];
|
||||
|
||||
if (cityName) {
|
||||
const city = cityOptions.value.find(item => item.name === cityName);
|
||||
if (city) {
|
||||
cityCode.value = city.code;
|
||||
form.value.addressCity = city.name;
|
||||
|
||||
const cityData = province.children?.find(item => item.code === city.code);
|
||||
if (cityData && cityData.children) {
|
||||
countyOptions.value = cityData.children.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
}));
|
||||
|
||||
if (countyName) {
|
||||
const county = countyOptions.value.find(item => item.name === countyName);
|
||||
if (county) {
|
||||
countyCode.value = county.code;
|
||||
form.value.addressCounty = county.name;
|
||||
|
||||
const countyData = cityData.children.find(item => item.code === county.code);
|
||||
if (countyData && countyData.children) {
|
||||
townOptions.value = countyData.children.map(item => ({
|
||||
code: item.code,
|
||||
name: item.name
|
||||
}));
|
||||
|
||||
if (townName) {
|
||||
const town = townOptions.value.find(item => item.name === townName);
|
||||
if (town) {
|
||||
townCode.value = town.code;
|
||||
form.value.addressTown = town.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -920,6 +1116,19 @@ function calculateAge() {
|
||||
*/
|
||||
function show(diagnosisData) {
|
||||
dialogVisible.value = true;
|
||||
|
||||
// 重置地址选择器状态
|
||||
provinceCode.value = '';
|
||||
cityCode.value = '';
|
||||
countyCode.value = '';
|
||||
townCode.value = '';
|
||||
cityOptions.value = [];
|
||||
countyOptions.value = [];
|
||||
townOptions.value = [];
|
||||
|
||||
// 初始化省级地址选项
|
||||
initProvinceOptions();
|
||||
|
||||
const patientInfo = props.patientInfo || {};
|
||||
const birthInfo = parseBirthDate(patientInfo.birthDate || patientInfo.birthday);
|
||||
|
||||
@@ -1019,37 +1228,16 @@ function show(diagnosisData) {
|
||||
updateSelectedDiseases();
|
||||
|
||||
// 设置地址选择组件初始值
|
||||
// 根据地址名称查找对应的代码数组
|
||||
const provName = diagnosisData?.addressProv || '';
|
||||
let cityName = diagnosisData?.addressCity || '';
|
||||
const cityName = diagnosisData?.addressCity || '';
|
||||
const countyName = diagnosisData?.addressCounty || '';
|
||||
const townName = diagnosisData?.addressTown || '';
|
||||
|
||||
// 处理直辖市情况:如果是直辖市,需要调整地址层级
|
||||
let names = [];
|
||||
if (municipalities.includes(provName)) {
|
||||
// 直辖市:省级=市级,所以传给级联选择器的应该是 [省, 区县, 街道]
|
||||
names = [provName, countyName, townName].filter(n => n);
|
||||
} else {
|
||||
// 非直辖市:正常处理 [省, 市, 区县, 街道]
|
||||
names = [provName, cityName, countyName, townName].filter(n => n);
|
||||
}
|
||||
addressCodes.value = findCodesByNames(names);
|
||||
initAddressByName(provName, cityName, countyName, townName);
|
||||
|
||||
if (birthInfo.year) {
|
||||
calculateAge();
|
||||
}
|
||||
|
||||
// 从后端获取下一个卡片编号(含流水号)
|
||||
getNextCardNo(orgCode).then(res => {
|
||||
if (res.code === 200 && res.data) {
|
||||
form.value.cardNo = res.data;
|
||||
}
|
||||
}).catch(err => {
|
||||
// 后端不可用时提示用户,不生成可能重复的编号
|
||||
proxy.$modal.msgError('获取卡片编号失败,请稍后重试');
|
||||
console.error('获取卡片编号失败:', err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1141,6 +1329,11 @@ async function buildSubmitData() {
|
||||
function validateFormManually() {
|
||||
const errors = [];
|
||||
|
||||
// 卡片编号验证(可选,但如果填写了必须是12位)
|
||||
if (form.value.cardNo && form.value.cardNo.length !== 12) {
|
||||
errors.push('卡片编号必须为12位');
|
||||
}
|
||||
|
||||
// 身份证号验证
|
||||
if (!form.value.idNo) {
|
||||
errors.push('请输入身份证号');
|
||||
@@ -1356,6 +1549,26 @@ defineExpose({ show });
|
||||
|
||||
.card-number-input {
|
||||
width: 240px;
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
border: none;
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
:deep(.el-input__inner::placeholder) {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
/* 表单区域样式 */
|
||||
@@ -1414,36 +1627,90 @@ defineExpose({ show });
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* 地址选择样式 */
|
||||
.address-inputs {
|
||||
/* 地址选择样式 - 四个下拉框并排 */
|
||||
.address-selects {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* 地址级联选择器样式 */
|
||||
.region-selects-wrapper {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.region-selects-wrapper :deep(.el-cascader) {
|
||||
width: 100%;
|
||||
.address-selects .el-select {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.region-selects-wrapper :deep(.el-cascader .el-input__wrapper) {
|
||||
.address-selects :deep(.el-input__wrapper) {
|
||||
border: none;
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.region-selects-wrapper :deep(.el-cascader .el-input__wrapper:hover) {
|
||||
.address-selects :deep(.el-input__wrapper:hover) {
|
||||
border-bottom-color: #c0c4cc;
|
||||
}
|
||||
|
||||
.region-selects-wrapper :deep(.el-cascader .el-input__wrapper.is-focus) {
|
||||
.address-selects :deep(.el-input__wrapper.is-focus) {
|
||||
border-bottom-color: #409eff;
|
||||
}
|
||||
|
||||
.address-selects :deep(.el-input__inner) {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.address-selects :deep(.el-input__inner::placeholder) {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 街道下拉框下划线样式 */
|
||||
.underline-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.underline-select :deep(.el-input__wrapper) {
|
||||
border: none;
|
||||
border-bottom: 1px solid #dcdfe6;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.underline-select :deep(.el-input__wrapper:hover) {
|
||||
border-bottom-color: #c0c4cc;
|
||||
}
|
||||
|
||||
.underline-select :deep(.el-input__wrapper.is-focus) {
|
||||
border-bottom-color: #409eff;
|
||||
}
|
||||
|
||||
.underline-select :deep(.el-input__inner) {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.underline-select :deep(.el-input__inner::placeholder) {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* 病例分类两行排布 */
|
||||
.case-class-group {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.case-class-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.case-class-row:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
|
||||
.full-select {
|
||||
width: 100%;
|
||||
@@ -1502,6 +1769,10 @@ defineExpose({ show });
|
||||
width: calc(25% - 8px);
|
||||
}
|
||||
|
||||
.disease-list.four-columns .el-checkbox.wide-checkbox {
|
||||
width: calc(50% - 8px);
|
||||
}
|
||||
|
||||
.disease-with-subtype {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -1533,6 +1804,9 @@ defineExpose({ show });
|
||||
.disease-with-subtype {
|
||||
width: calc(50% - 8px);
|
||||
}
|
||||
.disease-list.four-columns .el-checkbox.wide-checkbox {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<!-- 顶部操作按钮区 -->
|
||||
<el-header class="top-action-bar" height="50px">
|
||||
<el-row class="action-buttons" type="flex" justify="end" :gutter="10">
|
||||
<el-button type="success" size="large" @click="handleSave" class="save-btn">
|
||||
<el-button type="success" size="large" @click="handleSave" class="save-btn" :loading="saving">
|
||||
<el-icon><Document /></el-icon>
|
||||
保存
|
||||
</el-button>
|
||||
@@ -400,19 +400,35 @@
|
||||
<span class="card-title">检验项目选择</span>
|
||||
</template>
|
||||
|
||||
<!-- 搜索框 -->
|
||||
<el-input
|
||||
<!-- 搜索框(自动完成) -->
|
||||
<el-autocomplete
|
||||
v-model="searchKeyword"
|
||||
:fetch-suggestions="querySearchInspectionItems"
|
||||
placeholder="搜索检验项目..."
|
||||
size="small"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
@input="handleSearch"
|
||||
@select="handleSearchSelect"
|
||||
@clear="handleSearchClear"
|
||||
value-key="itemName"
|
||||
class="search-input"
|
||||
/>
|
||||
:debounce="300"
|
||||
>
|
||||
<template #default="{ item }">
|
||||
<div class="suggestion-item">
|
||||
<span class="suggestion-name">{{ item.itemName }}</span>
|
||||
<el-tag size="small" type="info" class="suggestion-category">{{ item.typeName || '检验' }}</el-tag>
|
||||
<span class="suggestion-price">¥{{ item.itemPrice }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
|
||||
<!-- 分类树 -->
|
||||
<el-scrollbar class="category-tree" style="max-height: 280px">
|
||||
<el-scrollbar
|
||||
class="category-tree"
|
||||
style="max-height: 280px"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<!-- 无数据提示 -->
|
||||
<el-empty v-if="!inspectionLoading && inspectionCategories.length === 0" description="暂无检验项目数据" :image-size="80" />
|
||||
<!-- 数据列表 -->
|
||||
@@ -427,9 +443,19 @@
|
||||
>
|
||||
<span class="category-tree-icon">{{ category.expanded ? '▼' : '▶' }}</span>
|
||||
<span>{{ category.label }}</span>
|
||||
<span class="category-count">({{ category.items.length }})</span>
|
||||
<span class="category-count">({{ category.total || category.items.length }})</span>
|
||||
<!-- 加载状态图标 -->
|
||||
<el-icon v-if="category.loading" class="is-loading" style="margin-left: 8px; color: #409eff;">
|
||||
<Loading />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div v-if="category.expanded" class="category-tree-children">
|
||||
<!-- 加载中占位 -->
|
||||
<div v-if="category.loading && category.items.length === 0" class="loading-placeholder">
|
||||
<el-icon class="is-loading" style="margin-right: 8px;"><Loading /></el-icon>
|
||||
<span>加载中...</span>
|
||||
</div>
|
||||
<!-- 项目列表 -->
|
||||
<div
|
||||
v-for="item in getFilteredItems(category.key)"
|
||||
:key="item.itemId"
|
||||
@@ -444,6 +470,22 @@
|
||||
<span class="item-itemName">{{ item.itemName }}</span>
|
||||
<span class="item-price">¥{{ item.itemPrice }}</span>
|
||||
</div>
|
||||
<!-- 加载更多 -->
|
||||
<div v-if="category.hasMore && category.items.length > 0" class="load-more">
|
||||
<el-button
|
||||
link
|
||||
size="small"
|
||||
:loading="category.loading"
|
||||
@click.stop="loadMoreItems(category.key)"
|
||||
>
|
||||
{{ category.loading ? '加载中...' : '加载更多' }}
|
||||
</el-button>
|
||||
<span class="load-info">(已加载 {{ category.items.length }}/{{ category.total }} 条)</span>
|
||||
</div>
|
||||
<!-- 加载完成提示 -->
|
||||
<div v-if="!category.hasMore && category.items.length > 0" class="no-more">
|
||||
已全部加载 (共 {{ category.total }} 条)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
@@ -492,18 +534,20 @@
|
||||
<script setup>
|
||||
import {onMounted, reactive, ref, watch, computed, getCurrentInstance} from 'vue'
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import { DocumentChecked, Plus, Document, Printer, Delete, Check } from '@element-plus/icons-vue'
|
||||
import { DocumentChecked, Plus, Document, Printer, Delete, Check, Loading } from '@element-plus/icons-vue'
|
||||
import {
|
||||
checkInspectionApplicationNo,
|
||||
deleteInspectionApplication, getApplyList,
|
||||
saveInspectionApplication,
|
||||
getInspectionTypeList,
|
||||
getInspectionItemList
|
||||
getInspectionItemList,
|
||||
getEncounterDiagnosis
|
||||
} from '../api'
|
||||
import useUserStore from '@/store/modules/user.js'
|
||||
// 迁移到 hiprint
|
||||
import { previewPrint } from '@/utils/printUtils.js'
|
||||
import {storeToRefs} from 'pinia'
|
||||
import { debounce } from 'lodash-es'
|
||||
|
||||
// 获取当前组件实例和字典
|
||||
const { proxy } = getCurrentInstance()
|
||||
@@ -532,6 +576,7 @@ const emit = defineEmits(['save'])
|
||||
|
||||
// 响应式数据
|
||||
const loading = ref(false)
|
||||
const saving = ref(false) // 保存状态
|
||||
const total = ref(0)
|
||||
const leftActiveTab = ref('application')
|
||||
const isGeneratingNewApplyNo = ref(false) // 标志:是否正在生成新申请单号
|
||||
@@ -561,6 +606,27 @@ async function initData() {
|
||||
generateApplicationNo().then((newApplyNo) => {
|
||||
formData.applyNo = newApplyNo
|
||||
})
|
||||
|
||||
// 获取主诊断信息
|
||||
try {
|
||||
const res = await getEncounterDiagnosis(props.patientInfo.encounterId)
|
||||
if (res.code === 200 && res.data && res.data.length > 0) {
|
||||
// 查找主诊断(maindiseFlag === 1)
|
||||
const mainDiagnosis = res.data.find(item => item.maindiseFlag === 1)
|
||||
if (mainDiagnosis) {
|
||||
formData.clinicDiag = mainDiagnosis.name || ''
|
||||
} else {
|
||||
// 没有主诊断时清空临床诊断
|
||||
formData.clinicDiag = ''
|
||||
}
|
||||
} else {
|
||||
// 没有诊断数据时清空临床诊断
|
||||
formData.clinicDiag = ''
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取主诊断信息失败:', error)
|
||||
formData.clinicDiag = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,7 +690,8 @@ const validationErrors = reactive({
|
||||
clinicDiag: false,
|
||||
medicalHistorySummary: false,
|
||||
purposeofInspection: false,
|
||||
labApplyItemList: false
|
||||
labApplyItemList: false,
|
||||
applyTime: false
|
||||
})
|
||||
|
||||
// 已选择的表格行
|
||||
@@ -639,15 +706,21 @@ const searchKeyword = ref('')
|
||||
// 活动分类
|
||||
const activeCategory = ref('')
|
||||
|
||||
// 检验项目分类(动态从API获取)
|
||||
// 检验项目分类(动态从API获取,支持懒加载和分页)
|
||||
const inspectionCategories = ref([])
|
||||
|
||||
// 检验项目加载状态
|
||||
// 检验项目加载状态(整体)
|
||||
const inspectionLoading = ref(false)
|
||||
|
||||
// 加载检验项目分类和项目
|
||||
// 每页加载条数
|
||||
const PAGE_SIZE = 50
|
||||
|
||||
// 搜索防抖时间(毫秒)
|
||||
const SEARCH_DEBOUNCE_TIME = 300
|
||||
|
||||
// 加载检验类型分类列表(只加载分类,项目懒加载)
|
||||
async function loadInspectionData() {
|
||||
// 如果已经加载过数据,直接返回(避免重复请求)
|
||||
// 如果已经加载过分类,直接返回
|
||||
if (inspectionCategories.value.length > 0) {
|
||||
return
|
||||
}
|
||||
@@ -655,194 +728,244 @@ async function loadInspectionData() {
|
||||
inspectionLoading.value = true
|
||||
|
||||
try {
|
||||
// 并行请求:同时获取检验类型列表和检验项目列表
|
||||
const [typeRes, itemRes] = await Promise.all([
|
||||
getInspectionTypeList().catch(error => {
|
||||
// 只获取检验类型列表
|
||||
const typeRes = await getInspectionTypeList().catch(error => {
|
||||
console.error('获取检验类型失败:', error)
|
||||
return { data: [] }
|
||||
}),
|
||||
getInspectionItemList({
|
||||
pageNo: 1,
|
||||
pageSize: 500,
|
||||
searchKey: '',
|
||||
categoryCode: inspectionCategoryCode.value
|
||||
}).catch(error => {
|
||||
console.error('获取检验项目失败:', error)
|
||||
return { data: { records: [] } }
|
||||
})
|
||||
])
|
||||
|
||||
const typeList = typeRes.data || []
|
||||
|
||||
// 解析检验项目数据
|
||||
let allItems = []
|
||||
if (itemRes.data && itemRes.data.records) {
|
||||
allItems = itemRes.data.records
|
||||
} else if (itemRes.data && Array.isArray(itemRes.data)) {
|
||||
allItems = itemRes.data
|
||||
} else if (Array.isArray(itemRes)) {
|
||||
allItems = itemRes
|
||||
}
|
||||
|
||||
// 按分类组织数据(与检验项目设置维护保持一致的字段映射)
|
||||
// 创建分类结构,但不加载项目(懒加载)
|
||||
const categories = typeList
|
||||
.filter(type => type.validFlag === 1 || type.validFlag === undefined)
|
||||
.map((type, index) => {
|
||||
const categoryItems = allItems
|
||||
.filter(item => {
|
||||
// 转换为字符串进行比较,避免类型不匹配问题
|
||||
const itemTypeId = String(item.inspectionTypeId || '')
|
||||
const typeId = String(type.id || '')
|
||||
const itemTypeName = String(item.inspectionTypeId_dictText || item.typeName || '').trim()
|
||||
const typeName = String(type.name || '').trim()
|
||||
|
||||
// 按检验类型ID匹配(优先使用 inspectionTypeId)
|
||||
const matchById = itemTypeId && typeId && itemTypeId === typeId
|
||||
const matchByName = itemTypeName && typeName && itemTypeName === typeName
|
||||
const matchByCode = String(item.typeCode || '') === String(type.code || '')
|
||||
|
||||
return matchById || matchByName || matchByCode
|
||||
})
|
||||
.map(item => ({
|
||||
itemId: item.id || item.activityId || Math.random().toString(36).substring(2, 11),
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
itemAmount: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
itemQty: 1,
|
||||
serviceFee: 0,
|
||||
type: type.name || item.inspectionTypeId_dictText || '检验',
|
||||
isSelfPay: false,
|
||||
activityId: item.activityId,
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
}))
|
||||
|
||||
return {
|
||||
.map((type, index) => ({
|
||||
key: type.code || `type_${index}`,
|
||||
label: type.name || `分类${index + 1}`,
|
||||
expanded: index === 0,
|
||||
items: categoryItems
|
||||
}
|
||||
})
|
||||
|
||||
// 过滤掉没有项目的分类
|
||||
const validCategories = categories.filter(cat => cat.items.length > 0)
|
||||
|
||||
// 如果没有有效分类,但有项目数据,按项目自带的检验类型文本分组
|
||||
if (validCategories.length === 0 && allItems.length > 0) {
|
||||
// 按检验类型文本分组
|
||||
const typeMap = new Map()
|
||||
allItems.forEach(item => {
|
||||
const typeName = item.inspectionTypeId_dictText || '其他检验'
|
||||
if (!typeMap.has(typeName)) {
|
||||
typeMap.set(typeName, [])
|
||||
}
|
||||
typeMap.get(typeName).push(item)
|
||||
})
|
||||
|
||||
// 创建分类
|
||||
typeMap.forEach((items, typeName) => {
|
||||
const mappedItems = items.map(item => ({
|
||||
itemId: item.id || item.activityId || Math.random().toString(36).substring(2, 11),
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
itemAmount: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
itemQty: 1,
|
||||
serviceFee: 0,
|
||||
type: typeName,
|
||||
isSelfPay: false,
|
||||
activityId: item.activityId,
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
typeId: type.id, // 保存类型ID用于分页查询
|
||||
expanded: index === 0, // 默认展开第一个
|
||||
loaded: false, // 是否已加载项目
|
||||
loading: false, // 是否正在加载
|
||||
items: [], // 项目列表
|
||||
pageNo: 1, // 当前页码
|
||||
pageSize: PAGE_SIZE, // 每页条数
|
||||
total: 0, // 总条数
|
||||
hasMore: true // 是否还有更多数据
|
||||
}))
|
||||
|
||||
validCategories.push({
|
||||
key: `type_${typeName}`,
|
||||
label: typeName,
|
||||
expanded: validCategories.length === 0,
|
||||
items: mappedItems
|
||||
})
|
||||
})
|
||||
}
|
||||
if (categories.length > 0) {
|
||||
inspectionCategories.value = categories
|
||||
activeCategory.value = categories[0].key
|
||||
|
||||
if (validCategories.length > 0) {
|
||||
inspectionCategories.value = validCategories
|
||||
activeCategory.value = validCategories[0].key
|
||||
// 预加载第一个分类的项目
|
||||
await loadCategoryItems(categories[0].key)
|
||||
} else {
|
||||
console.warn('未获取到有效的检验项目数据,使用备用数据')
|
||||
// 直接使用备用数据,不抛出错误
|
||||
inspectionCategories.value = [
|
||||
{
|
||||
key: 'biochemical',
|
||||
label: '生化',
|
||||
expanded: true,
|
||||
items: [
|
||||
{ itemId: 1, itemName: '肝功能', itemPrice: 31, itemAmount: 31, sampleType: '血清', unit: 'U/L', itemQty: 1, serviceFee: 0, type: '生化', isSelfPay: false },
|
||||
{ itemId: 2, itemName: '肾功能', itemPrice: 28, itemAmount: 28, sampleType: '血清', unit: 'U/L', itemQty: 1, serviceFee: 0, type: '生化', isSelfPay: false },
|
||||
{ itemId: 3, itemName: '血糖', itemPrice: 15, itemAmount: 15, sampleType: '血清', unit: 'mmol/L', itemQty: 1, serviceFee: 0, type: '生化', isSelfPay: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'blood',
|
||||
label: '临检',
|
||||
expanded: false,
|
||||
items: [
|
||||
{ itemId: 4, itemName: '血常规+crp', itemPrice: 50, itemAmount: 50, sampleType: '全血', unit: '×10^9/L', itemQty: 1, serviceFee: 0, type: '血液', isSelfPay: false },
|
||||
{ itemId: 5, itemName: '血常规(五分类)', itemPrice: 15, itemAmount: 15, sampleType: '全血', unit: '×10^9/L', itemQty: 1, serviceFee: 0, type: '血液', isSelfPay: false }
|
||||
]
|
||||
}
|
||||
]
|
||||
activeCategory.value = 'biochemical'
|
||||
console.warn('未获取到检验类型分类')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载检验项目数据失败:', error)
|
||||
// 加载失败时使用静态数据作为备用
|
||||
inspectionCategories.value = [
|
||||
{
|
||||
key: 'biochemical',
|
||||
label: '生化',
|
||||
expanded: true,
|
||||
items: [
|
||||
{ itemId: 1, itemName: '肝功能', itemPrice: 31, itemAmount: 31, sampleType: '血清', unit: 'U/L', itemQty: 1, serviceFee: 0, type: '生化', isSelfPay: false },
|
||||
{ itemId: 2, itemName: '肾功能', itemPrice: 28, itemAmount: 28, sampleType: '血清', unit: 'U/L', itemQty: 1, serviceFee: 0, type: '生化', isSelfPay: false },
|
||||
{ itemId: 3, itemName: '血糖', itemPrice: 15, itemAmount: 15, sampleType: '血清', unit: 'mmol/L', itemQty: 1, serviceFee: 0, type: '生化', isSelfPay: false }
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'blood',
|
||||
label: '临检',
|
||||
expanded: false,
|
||||
items: [
|
||||
{ itemId: 4, itemName: '血常规+crp', itemPrice: 50, itemAmount: 50, sampleType: '全血', unit: '×10^9/L', itemQty: 1, serviceFee: 0, type: '血液', isSelfPay: false },
|
||||
{ itemId: 5, itemName: '血常规(五分类)', itemPrice: 15, itemAmount: 15, sampleType: '全血', unit: '×10^9/L', itemQty: 1, serviceFee: 0, type: '血液', isSelfPay: false }
|
||||
]
|
||||
}
|
||||
]
|
||||
activeCategory.value = 'biochemical'
|
||||
console.error('加载检验类型分类失败:', error)
|
||||
} finally {
|
||||
inspectionLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 获取过滤后的项目
|
||||
// 懒加载分类项目(分页)
|
||||
async function loadCategoryItems(categoryKey, loadMore = false) {
|
||||
const category = inspectionCategories.value.find(c => c.key === categoryKey)
|
||||
if (!category) return
|
||||
|
||||
// 已加载完成且不是加载更多,或正在加载中,跳过
|
||||
if ((category.loaded && !loadMore) || category.loading) return
|
||||
// 没有更多数据了,跳过
|
||||
if (loadMore && !category.hasMore) return
|
||||
|
||||
category.loading = true
|
||||
|
||||
try {
|
||||
const params = {
|
||||
pageNo: category.pageNo,
|
||||
pageSize: category.pageSize,
|
||||
categoryCode: inspectionCategoryCode.value,
|
||||
searchKey: searchKeyword.value || ''
|
||||
}
|
||||
|
||||
// 如果有类型ID,添加筛选条件
|
||||
if (category.typeId) {
|
||||
params.inspectionTypeId = category.typeId
|
||||
}
|
||||
|
||||
const res = await getInspectionItemList(params)
|
||||
|
||||
// 解析数据
|
||||
let records = []
|
||||
let total = 0
|
||||
if (res.data && res.data.records) {
|
||||
records = res.data.records
|
||||
total = res.data.total || 0
|
||||
} else if (res.data && Array.isArray(res.data)) {
|
||||
records = res.data
|
||||
total = records.length
|
||||
} else if (Array.isArray(res)) {
|
||||
records = res
|
||||
total = records.length
|
||||
}
|
||||
|
||||
// 映射数据格式
|
||||
const mappedItems = records.map(item => ({
|
||||
itemId: item.id || item.activityId || Math.random().toString(36).substring(2, 11),
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
itemAmount: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
itemQty: 1,
|
||||
serviceFee: 0,
|
||||
type: category.label,
|
||||
isSelfPay: false,
|
||||
activityId: item.activityId,
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
}))
|
||||
|
||||
// 更新分类数据
|
||||
if (loadMore) {
|
||||
// 追加数据
|
||||
category.items.push(...mappedItems)
|
||||
} else {
|
||||
// 首次加载
|
||||
category.items = mappedItems
|
||||
}
|
||||
|
||||
category.total = total
|
||||
category.hasMore = category.items.length < total
|
||||
category.loaded = true
|
||||
|
||||
} catch (error) {
|
||||
console.error(`加载分类 [${category.label}] 项目失败:`, error)
|
||||
// 加载失败时设置空数据
|
||||
if (!loadMore) {
|
||||
category.items = []
|
||||
category.total = 0
|
||||
category.hasMore = false
|
||||
category.loaded = true
|
||||
}
|
||||
} finally {
|
||||
category.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
// 加载更多项目
|
||||
function loadMoreItems(categoryKey) {
|
||||
const category = inspectionCategories.value.find(c => c.key === categoryKey)
|
||||
if (!category || !category.hasMore || category.loading) return
|
||||
|
||||
category.pageNo++
|
||||
loadCategoryItems(categoryKey, true)
|
||||
}
|
||||
|
||||
// 处理滚动事件(无限滚动)
|
||||
function handleScroll({ scrollTop, scrollHeight, clientHeight }) {
|
||||
// 距离底部 50px 时触发加载更多
|
||||
if (scrollHeight - scrollTop - clientHeight < 50) {
|
||||
const expandedCategory = inspectionCategories.value.find(c => c.expanded)
|
||||
if (expandedCategory && expandedCategory.hasMore && !expandedCategory.loading) {
|
||||
loadMoreItems(expandedCategory.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 防抖搜索处理
|
||||
const handleSearchDebounced = debounce(() => {
|
||||
// 重新加载当前展开分类的数据
|
||||
const expandedCategory = inspectionCategories.value.find(c => c.expanded)
|
||||
if (expandedCategory) {
|
||||
// 重置分页状态
|
||||
expandedCategory.pageNo = 1
|
||||
expandedCategory.loaded = false
|
||||
expandedCategory.hasMore = true
|
||||
expandedCategory.items = []
|
||||
// 重新加载
|
||||
loadCategoryItems(expandedCategory.key)
|
||||
}
|
||||
}, SEARCH_DEBOUNCE_TIME)
|
||||
|
||||
// 获取过滤后的项目(本地搜索)
|
||||
const getFilteredItems = (categoryKey) => {
|
||||
const category = inspectionCategories.value.find(cat => cat.key === categoryKey)
|
||||
if (!category) return []
|
||||
|
||||
if (!searchKeyword.value) {
|
||||
// 如果正在加载,返回现有数据
|
||||
if (category.loading) {
|
||||
return category.items
|
||||
}
|
||||
|
||||
// 本地过滤(安全检查 itemName)
|
||||
if (searchKeyword.value) {
|
||||
const keyword = searchKeyword.value.toLowerCase()
|
||||
return category.items.filter(item =>
|
||||
item.itemName.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
||||
item.itemName && item.itemName.toLowerCase().includes(keyword)
|
||||
)
|
||||
}
|
||||
|
||||
return category.items
|
||||
}
|
||||
|
||||
// 搜索建议查询(自动完成)
|
||||
async function querySearchInspectionItems(queryString, cb) {
|
||||
if (!queryString) {
|
||||
cb([])
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const params = {
|
||||
pageNo: 1,
|
||||
pageSize: 20, // 限制返回数量
|
||||
categoryCode: inspectionCategoryCode.value,
|
||||
searchKey: queryString
|
||||
}
|
||||
|
||||
const res = await getInspectionItemList(params)
|
||||
|
||||
let suggestions = []
|
||||
if (res.data && res.data.records) {
|
||||
// 映射数据格式,与 loadInspectionItemsByType 保持一致
|
||||
suggestions = res.data.records.map(item => ({
|
||||
itemId: item.id || item.activityId,
|
||||
itemName: item.name || item.itemName || '',
|
||||
itemPrice: item.retailPrice || item.price || 0,
|
||||
sampleType: item.specimenCode_dictText || item.sampleType || '血液',
|
||||
unit: item.unit || '',
|
||||
code: item.busNo || item.code || item.activityCode,
|
||||
activityId: item.activityId,
|
||||
inspectionTypeId: item.inspectionTypeId || null
|
||||
}))
|
||||
}
|
||||
|
||||
cb(suggestions)
|
||||
} catch (error) {
|
||||
console.error('搜索检验项目失败:', error)
|
||||
cb([])
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索选择处理
|
||||
function handleSearchSelect(item) {
|
||||
// 直接添加到已选列表
|
||||
if (!isItemSelected(item)) {
|
||||
selectedInspectionItems.value.push({
|
||||
...item,
|
||||
itemName: item.itemName
|
||||
})
|
||||
}
|
||||
// 清空搜索关键词
|
||||
searchKeyword.value = ''
|
||||
}
|
||||
|
||||
// 搜索框清空处理
|
||||
function handleSearchClear() {
|
||||
searchKeyword.value = ''
|
||||
}
|
||||
|
||||
// 获取检验申请单列表
|
||||
function getInspectionList() {
|
||||
@@ -1050,10 +1173,35 @@ async function resetForm() {
|
||||
})
|
||||
|
||||
formRef.value?.clearValidate()
|
||||
|
||||
// 获取主诊断信息
|
||||
if (props.patientInfo && props.patientInfo.encounterId) {
|
||||
try {
|
||||
const res = await getEncounterDiagnosis(props.patientInfo.encounterId)
|
||||
if (res.code === 200 && res.data && res.data.length > 0) {
|
||||
const mainDiagnosis = res.data.find(item => item.maindiseFlag === 1)
|
||||
if (mainDiagnosis) {
|
||||
formData.clinicDiag = mainDiagnosis.name || ''
|
||||
} else {
|
||||
// 没有主诊断时清空临床诊断
|
||||
formData.clinicDiag = ''
|
||||
}
|
||||
} else {
|
||||
// 没有诊断数据时清空临床诊断
|
||||
formData.clinicDiag = ''
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取主诊断信息失败:', error)
|
||||
formData.clinicDiag = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 保存
|
||||
function handleSave() {
|
||||
// 如果正在保存,直接返回
|
||||
if (saving.value) return
|
||||
|
||||
// 重置验证错误状态
|
||||
Object.keys(validationErrors).forEach(key => {
|
||||
validationErrors[key] = false
|
||||
@@ -1061,29 +1209,28 @@ function handleSave() {
|
||||
|
||||
let hasErrors = false
|
||||
|
||||
// 检查必填字段
|
||||
// 检查必填字段,执行科室
|
||||
if (!formData.executeDepartment) {
|
||||
validationErrors.executeDepartment = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,诊断描述
|
||||
if (!formData.clinicDesc.trim()) {
|
||||
if (!formData.clinicDesc?.trim()) {
|
||||
validationErrors.clinicDesc = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,临床诊断
|
||||
if (!formData.clinicDiag.trim()) {
|
||||
if (!formData.clinicDiag?.trim()) {
|
||||
validationErrors.clinicDiag = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,病史摘要
|
||||
if (!formData.medicalHistorySummary.trim()) {
|
||||
if (!formData.medicalHistorySummary?.trim()) {
|
||||
validationErrors.medicalHistorySummary = true
|
||||
hasErrors = true
|
||||
}
|
||||
// 检查必填字段,检验目的
|
||||
if (!formData.purposeofInspection.trim()) {
|
||||
if (!formData.purposeofInspection?.trim()) {
|
||||
validationErrors.purposeofInspection = true
|
||||
hasErrors = true
|
||||
}
|
||||
@@ -1095,7 +1242,7 @@ function handleSave() {
|
||||
return
|
||||
}
|
||||
// 检查必填字段,申请日期
|
||||
if(!formData.applyTime || (typeof formData.applyTime === 'string' && !formData.applyTime.trim())) {
|
||||
if(!formData.applyTime || (typeof formData.applyTime === 'string' && !formData.applyTime?.trim())) {
|
||||
validationErrors.applyTime = true
|
||||
hasErrors = true
|
||||
}
|
||||
@@ -1182,9 +1329,11 @@ function handleSave() {
|
||||
|
||||
}
|
||||
const executeSave = (saveData) => {
|
||||
saving.value = true
|
||||
saveInspectionApplication(saveData).then((res) => {
|
||||
if (res.code === 200) {
|
||||
ElMessage.success('保存成功')
|
||||
emit('save', res.data) // 通知父组件保存成功
|
||||
resetForm()
|
||||
// 生成新的申请单号
|
||||
generateApplicationNo().then((newApplyNo) => {
|
||||
@@ -1211,6 +1360,8 @@ const executeSave = (saveData) => {
|
||||
// 处理请求失败的其他错误
|
||||
console.error('保存检验申请单时发生错误:', error);
|
||||
ElMessage.error('保存失败,请稍后重试');
|
||||
}).finally(() => {
|
||||
saving.value = false
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1222,10 +1373,10 @@ function handleView(row) {
|
||||
|
||||
// 根据检验项目名称找到对应的项目数据
|
||||
selectedInspectionItems.value = []
|
||||
const itemNames = row.inspectionItem.split('、')
|
||||
const itemNames = row.itemName?.split('、') || row.inspectionItem?.split('、') || []
|
||||
inspectionCategories.value.forEach(category => {
|
||||
category.items.forEach(item => {
|
||||
if (itemNames.includes(item.name)) {
|
||||
if (itemNames.includes(item.itemName)) {
|
||||
selectedInspectionItems.value.push(item)
|
||||
}
|
||||
})
|
||||
@@ -1234,7 +1385,7 @@ function handleView(row) {
|
||||
leftActiveTab.value = 'application'
|
||||
}
|
||||
|
||||
// 切换分类
|
||||
// 切换分类(修改为懒加载)
|
||||
function switchCategory(category) {
|
||||
if (activeCategory.value === category) {
|
||||
// 如果点击的是当前激活的分类,则收起
|
||||
@@ -1250,12 +1401,13 @@ function switchCategory(category) {
|
||||
inspectionCategories.value.forEach(cat => {
|
||||
cat.expanded = cat.key === category
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 处理搜索
|
||||
function handleSearch() {
|
||||
// 搜索逻辑已在getFilteredItems中实现
|
||||
// 懒加载该分类的项目
|
||||
const targetCategory = inspectionCategories.value.find(c => c.key === category)
|
||||
if (targetCategory && !targetCategory.loaded) {
|
||||
loadCategoryItems(category)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理项目项点击(排除勾选框点击)
|
||||
@@ -1409,8 +1561,8 @@ function handleCellClick(row, column) {
|
||||
|
||||
// 根据检验项目名称解析已选项目
|
||||
selectedInspectionItems.value = []
|
||||
if (row.inspectionItem) {
|
||||
const itemNames = row.inspectionItem.split('、')
|
||||
if (row.itemName || row.inspectionItem) {
|
||||
const itemNames = (row.itemName || row.inspectionItem).split('、')
|
||||
inspectionCategories.value.forEach(category => {
|
||||
category.items.forEach(item => {
|
||||
if (itemNames.includes(item.itemName)) {
|
||||
@@ -1956,6 +2108,39 @@ defineExpose({
|
||||
border-top: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
/* 加载中占位样式 */
|
||||
.loading-placeholder {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* 加载更多样式 */
|
||||
.load-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border-top: 1px dashed #ebeef5;
|
||||
}
|
||||
|
||||
.load-info {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
/* 没有更多数据提示 */
|
||||
.no-more {
|
||||
text-align: center;
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.inspection-tree-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -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
|
||||
};
|
||||
});
|
||||
|
||||
@@ -2076,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;
|
||||
}
|
||||
@@ -2260,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) {
|
||||
@@ -2338,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,
|
||||
@@ -2346,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
|
||||
};
|
||||
});
|
||||
// --- 【修改结束】 ---
|
||||
@@ -2361,6 +2510,9 @@ function handleSaveBatch(prescriptionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 🔧 调试:查看保存时的完整参数
|
||||
console.log('【保存】完整请求参数:', JSON.stringify(saveList, null, 2));
|
||||
|
||||
isSaving.value = true;
|
||||
|
||||
// 本地临时更新状态,让用户立即看到保存效果
|
||||
@@ -2505,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();
|
||||
@@ -2863,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);
|
||||
|
||||
@@ -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,14 +230,41 @@ 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) => {
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,17 +436,45 @@ 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;
|
||||
}
|
||||
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, // 不设默认值
|
||||
medTypeCode: undefined,
|
||||
diagSrtNo: form.value.diagnosisList.length + 1,
|
||||
iptDiseTypeCode: 2,
|
||||
diagnosisDesc: '',
|
||||
@@ -425,8 +484,7 @@ function handleAddDiagnosis() {
|
||||
if (form.value.diagnosisList.length == 1) {
|
||||
form.value.diagnosisList[0].maindiseFlag = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
console.log('添加完成,新列表长度:', form.value.diagnosisList.length);
|
||||
}
|
||||
|
||||
// 添加中医诊断
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -396,20 +396,28 @@ 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 = res.data.admittingDoctorId;
|
||||
interventionForm.value.admittingDoctorId = String(res.data.admittingDoctorId);
|
||||
}
|
||||
if (res.data.attendingDoctorId) {
|
||||
interventionForm.value.attendingDoctorId = res.data.attendingDoctorId;
|
||||
interventionForm.value.attendingDoctorId = String(res.data.attendingDoctorId);
|
||||
}
|
||||
if (res.data.chiefDoctorId) {
|
||||
interventionForm.value.chiefDoctorId = res.data.chiefDoctorId;
|
||||
interventionForm.value.chiefDoctorId = String(res.data.chiefDoctorId);
|
||||
}
|
||||
if (res.data.primaryNurseId) {
|
||||
interventionForm.value.primaryNurseId = res.data.primaryNurseId;
|
||||
// 护士ID也转换为字符串以匹配护士选项
|
||||
interventionForm.value.primaryNurseId = String(res.data.primaryNurseId);
|
||||
}
|
||||
if (res.data.startTime) {
|
||||
interventionForm.value.startTime = dayjs(res.data.startTime).format(
|
||||
@@ -435,21 +443,23 @@ const loadPatientInfo = () => {
|
||||
watch(
|
||||
() => props.pendingInfo?.encounterId,
|
||||
(newVal, oldVal) => {
|
||||
// 只在 encounterId 存在且发生变化时才获取数据
|
||||
if (newVal && newVal !== oldVal) {
|
||||
// encounterId 存在时就获取数据
|
||||
if (newVal) {
|
||||
console.log('watch 触发, newVal:', newVal, 'oldVal:', oldVal);
|
||||
loadPatientInfo();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
}
|
||||
);
|
||||
|
||||
/* 初始化数据 */
|
||||
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;
|
||||
}
|
||||
@@ -457,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 || [];
|
||||
})
|
||||
@@ -467,16 +478,18 @@ 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) => {
|
||||
doctorInfoOptions.value = res.data.records || [];
|
||||
// 只有在新分配床位模式(entranceType != 1)时才设置默认主任医生
|
||||
// 并且只在当前没有选择主任医生时才设置默认值(避免覆盖已从后端获取的数据)
|
||||
if (props.pendingInfo.entranceType != 1) {
|
||||
nextTick(() => {
|
||||
// 如果存在主任医师显示主任,如果没有选择第一个展示
|
||||
if (doctorInfoOptions.value.length > 0) {
|
||||
if (doctorInfoOptions.value.length > 0 && !interventionForm.value.chiefDoctorId) {
|
||||
let selectId = '';
|
||||
doctorInfoOptions.value.forEach((item: any) => {
|
||||
if (item.drProfttlCode == '231') {
|
||||
@@ -490,21 +503,30 @@ const init = () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
.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>({
|
||||
@@ -544,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,9 +616,10 @@ const handleSubmit = async () => {
|
||||
};
|
||||
|
||||
const openAct = () => {
|
||||
init();
|
||||
// 重新加载患者详细信息(包括医生、护士等)
|
||||
// 先初始化数据(包括医生护士列表),等待完成后再加载患者信息
|
||||
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({});
|
||||
|
||||
@@ -486,6 +486,14 @@
|
||||
{{ getCheckTypeLabel(item.checkType) || '无' }}
|
||||
</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">
|
||||
<el-select
|
||||
@@ -872,41 +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 = [];
|
||||
}
|
||||
|
||||
// 从检查类型维护界面获取所有检查类型(用于下拉选项)
|
||||
try {
|
||||
const checkTypeListResponse = await getAllCheckTypes();
|
||||
if (checkTypeListResponse && checkTypeListResponse.data) {
|
||||
// 处理返回的数据,提取 name 和 code/type 用于下拉选项
|
||||
const typeList = Array.isArray(checkTypeListResponse.data)
|
||||
? checkTypeListResponse.data
|
||||
: (checkTypeListResponse.data.records || []);
|
||||
checkTypeOptions.value = typeList.map(item => ({
|
||||
value: item.code || item.type || item.id,
|
||||
label: item.name,
|
||||
id: item.id,
|
||||
code: item.code,
|
||||
type: item.type
|
||||
}));
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('获取检查类型列表失败', e);
|
||||
checkTypeOptions.value = [];
|
||||
}
|
||||
|
||||
// 获取服务范围数据(从数据字典获取)
|
||||
const scopeResponse = await getDicts('scope_of_services');
|
||||
if (scopeResponse && scopeResponse.data) {
|
||||
// 保存完整的服务范围字典数据
|
||||
serviceScopeDicts.value = scopeResponse.data;
|
||||
} else {
|
||||
serviceScopeDicts.value = [];
|
||||
}
|
||||
|
||||
// 获取检查类型表格数据(分页获取)
|
||||
await loadCheckTypeDataWithPagination();
|
||||
|
||||
@@ -1244,14 +1229,30 @@ async function handleConfirm(index) {
|
||||
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 (activeMenu.value === '检查类型') {
|
||||
if (!item.department || item.department.trim() === '') {
|
||||
ElMessage.error('执行科室不能为空');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// 根据当前激活的菜单调用不同的API
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user