diff --git a/healthlink-his-server/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java b/healthlink-his-server/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java index 611ce1d3d..dd0c499b0 100755 --- a/healthlink-his-server/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java +++ b/healthlink-his-server/core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java @@ -42,8 +42,10 @@ public class ApplicationConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); - mapper.setTimeZone(TimeZone.getDefault()); - mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); + mapper.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); + mapper.setDateFormat(sdf); mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); JavaTimeModule javaTimeModule = new JavaTimeModule(); diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/common/dto/PerformRecordDto.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/common/dto/PerformRecordDto.java index bde3e6c01..72d4abbb2 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/common/dto/PerformRecordDto.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/common/dto/PerformRecordDto.java @@ -30,11 +30,11 @@ public class PerformRecordDto { private String statusEnum_enumText; /** 预计执行时间 */ - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") private Date occurrenceTime; /** 实际执行时间 */ - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai") private Date recordedTime; /** 执行位置 */ diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java index af324bad0..adeea9d03 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/inhospitalnursestation/appservice/impl/AdviceProcessAppServiceImpl.java @@ -74,6 +74,13 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), DateTimeFormatter.ofPattern("yyyy-MM-dd H:mm:ss")); + /** Date → "yyyy-MM-dd HH:mm:ss",与前端 formatDateStr 输出格式一致 */ + private static String formatOccurrenceTime(Date date) { + if (date == null) return ""; + LocalDateTime ldt = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); + return ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } + @Resource AssignSeqUtil assignSeqUtil; @@ -334,7 +341,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { if (performRecordList != null && !performRecordList.isEmpty()) { // 按时间分组,处理每个时间点的多条记录 Map> recordsByTime = performRecordList.stream() - .collect(Collectors.groupingBy(record -> record.getOccurrenceTime().toString())); + .collect(Collectors.groupingBy(record -> formatOccurrenceTime(record.getOccurrenceTime()))); for (Map.Entry> entry : recordsByTime.entrySet()) { List records = entry.getValue(); // 按操作顺序排序 @@ -563,12 +570,25 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { Date exeDate = adviceExecuteParam.getExeDate(); // 医嘱集合 List adviceExecuteDetailList = adviceExecuteParam.getAdviceExecuteDetailList(); + + // 前置校验:确保有待执行的医嘱且 executeTimes 不为空 + if (adviceExecuteDetailList == null || adviceExecuteDetailList.isEmpty()) { + return R.fail("未选择需要执行的医嘱"); + } + adviceExecuteDetailList.removeIf(item -> item.getExecuteTimes() == null || item.getExecuteTimes().isEmpty()); + if (adviceExecuteDetailList.isEmpty()) { + return R.fail("所选医嘱没有可执行的时间点,请勾选预计执行时间后再操作"); + } + // 药品 List medicineList = adviceExecuteDetailList.stream() .filter(e -> CommonConstants.TableName.MED_MEDICATION_REQUEST.equals(e.getAdviceTable())).toList(); // 诊疗 List activityList = adviceExecuteDetailList.stream() .filter(e -> CommonConstants.TableName.WOR_SERVICE_REQUEST.equals(e.getAdviceTable())).toList(); + + int totalCreatedCount = 0; + // -------------------------------------------药品 if (!medicineList.isEmpty()) { // 组装药品请求用于执行的数据结构 @@ -581,14 +601,14 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { } } // 处理药品执行 - this.exeMedication(medUseExeList, exeDate); + totalCreatedCount += this.exeMedication(medUseExeList, exeDate); } // -------------------------------------------诊疗 if (!activityList.isEmpty()) { // 组装诊疗请求用于执行的数据结构 List actUseExeList = this.assemblyActivity(activityList); // 处理诊疗执行 - this.exeActivity(actUseExeList, exeDate); + totalCreatedCount += this.exeActivity(actUseExeList, exeDate); // 检查类医嘱执行后,状态改为"待接收"(PENDING_RECEIVE=11) List actReqIds = activityList.stream().map(AdviceExecuteDetailParam::getRequestId).toList(); List executedReqs = serviceRequestService.listByIds(actReqIds); @@ -607,6 +627,11 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { } } + // 后置校验:确认有执行记录被实际创建 + if (totalCreatedCount == 0) { + return R.fail("执行失败,未生成任何执行记录,请检查医嘱状态后重试"); + } + return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"医嘱执行"})); } @@ -908,8 +933,10 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { * * @param medUseExeList 药品医嘱 * @param exeDate 实际执行时间 + * @return 实际创建的执行记录数 */ - private void exeMedication(List medUseExeList, Date exeDate) { + private int exeMedication(List medUseExeList, Date exeDate) { + int createdCount = 0; // 长期医嘱 List longMedication = medUseExeList.stream() .filter(e -> TherapyTimeType.LONG_TERM.getValue().equals(e.getTherapyEnum())).toList(); @@ -932,6 +959,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { MedicationRequest longMedicationRequest; ChargeItem chargeItem; for (MedicationRequestUseExe medicationRequestUseExe : longMedication) { + if (medicationRequestUseExe.getExecuteTimes() == null) continue; for (String executeTime : medicationRequestUseExe.getExecuteTimes()) { longMedicationRequest = new MedicationRequest(); BeanUtils.copyProperties(medicationRequestUseExe, longMedicationRequest); @@ -961,6 +989,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { CommonConstants.TableName.MED_MEDICATION_REQUEST, EventStatus.COMPLETED, ProcedureCategory.INPATIENT_ADVICE, null, expectedDate, exeDate, longMedicationRequest.getGroupId(), null); + createdCount++; // 医嘱定价来源 String orderPricingSource = TenantOptionUtil.getOptionContent(TenantOptionDict.ORDER_PRICING_SOURCE); @@ -1161,6 +1190,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { // 临时 MedicationRequest tempMedicationRequest; for (MedicationRequestUseExe medicationRequestUseExe : tempMedication) { + if (medicationRequestUseExe.getExecuteTimes() == null) continue; for (String executeTime : medicationRequestUseExe.getExecuteTimes()) { tempMedicationRequest = new MedicationRequest(); BeanUtils.copyProperties(medicationRequestUseExe, tempMedicationRequest); @@ -1173,6 +1203,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { CommonConstants.TableName.MED_MEDICATION_REQUEST, EventStatus.COMPLETED, ProcedureCategory.INPATIENT_ADVICE, null, expectedDate, exeDate, tempMedicationRequest.getGroupId(), null); + createdCount++; // 更新药品放发状态 medicationDispenseService.update(new LambdaUpdateWrapper() @@ -1189,6 +1220,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { } } + return createdCount; } /** @@ -1196,8 +1228,10 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { * * @param actUseExeList 诊疗医嘱 * @param exeDate 实际执行时间 + * @return 实际创建的执行记录数 */ - private void exeActivity(List actUseExeList, Date exeDate) { + private int exeActivity(List actUseExeList, Date exeDate) { + int createdCount = 0; // 长期医嘱 List longActivity = actUseExeList.stream() .filter(e -> TherapyTimeType.LONG_TERM.getValue().equals(e.getTherapyEnum())).toList(); @@ -1222,6 +1256,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { ServiceRequest longServiceRequest; ChargeItem chargeItem; for (ServiceRequestUseExe serviceRequestUseExe : longActivity) { + if (serviceRequestUseExe.getExecuteTimes() == null) continue; // 查询耗材的取药科室 Long takeDeviceLocationId = doctorStationAdviceAppMapper .getTakeDeviceLocationId(serviceRequestUseExe.getEncounterId(), ItemCategoryCode.DEVICE.getCode()); @@ -1236,6 +1271,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { longServiceRequest.getPatientId(), longServiceRequest.getId(), CommonConstants.TableName.WOR_SERVICE_REQUEST, EventStatus.COMPLETED, ProcedureCategory.INPATIENT_ADVICE, null, expectedDate, exeDate, null, null); + createdCount++; // 生成账单 chargeItem = new ChargeItem(); @@ -1293,6 +1329,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { // 临时 ServiceRequest tempServiceRequest; for (ServiceRequestUseExe serviceRequestUseExe : tempActivity) { + if (serviceRequestUseExe.getExecuteTimes() == null) continue; // 查询耗材的取药科室 Long takeDeviceLocationId = doctorStationAdviceAppMapper .getTakeDeviceLocationId(serviceRequestUseExe.getEncounterId(), ItemCategoryCode.DEVICE.getCode()); @@ -1307,6 +1344,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { tempServiceRequest.getPatientId(), tempServiceRequest.getId(), CommonConstants.TableName.WOR_SERVICE_REQUEST, EventStatus.COMPLETED, ProcedureCategory.INPATIENT_ADVICE, null, expectedDate, exeDate, null, null); + createdCount++; // 更新账单状态 chargeItemService.update( @@ -1324,6 +1362,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService { } } + return createdCount; } /** diff --git a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/regdoctorstation/dto/RegRequestBaseDto.java b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/regdoctorstation/dto/RegRequestBaseDto.java index 2559d9638..3fcd684ef 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/regdoctorstation/dto/RegRequestBaseDto.java +++ b/healthlink-his-server/healthlink-his-application/src/main/java/com/healthlink/his/web/regdoctorstation/dto/RegRequestBaseDto.java @@ -51,6 +51,9 @@ public class RegRequestBaseDto extends RequestBaseDto { private String doseUnitCode_dictText; + /** 药品分类编码(1-中成药 2-西药 4-中草药) */ + private String categoryCode; + /** * 备注(最长50字) */ diff --git a/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/regdoctorstation/AdviceManageAppMapper.xml b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/regdoctorstation/AdviceManageAppMapper.xml index d410d599e..f1df52205 100755 --- a/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/regdoctorstation/AdviceManageAppMapper.xml +++ b/healthlink-his-server/healthlink-his-application/src/main/resources/mapper/regdoctorstation/AdviceManageAppMapper.xml @@ -197,6 +197,7 @@ T1.infusion_flag AS inject_flag, T1.group_id AS group_id, T2.NAME AS advice_name, + T2.category_code AS category_code, T3.total_volume AS volume, T1.lot_number AS lot_number, T1.quantity AS quantity, @@ -256,6 +257,7 @@ null AS inject_flag, null AS group_id, T2.NAME AS advice_name, + '' AS category_code, T2.SIZE AS volume, T1.lot_number AS lot_number, T1.quantity AS quantity, @@ -312,6 +314,7 @@ null AS inject_flag, null AS group_id, COALESCE(T2.NAME, T1.content_json::jsonb->>'surgeryName', T1.content_json::jsonb->>'adviceName') AS advice_name, + '' AS category_code, '' AS volume, '' AS lot_number, T1.quantity AS quantity, diff --git a/healthlink-his-ui/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue b/healthlink-his-ui/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue index 5618bca0c..fc4c2f48d 100755 --- a/healthlink-his-ui/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue +++ b/healthlink-his-ui/src/views/inpatientDoctor/home/components/applicationShow/surgeryApplication.vue @@ -277,7 +277,7 @@ currentDetail.createTime || '-' }} - + {{ currentDetail.prescriptionNo || '-' }} @@ -574,13 +574,7 @@ const handleEdit = async (row) => { editFormRef.value?.getLocationInfo?.(); editFormRef.value?.getDiagnosisList?.(); editFormRef.value?.loadDoctorOptions?.(); - if (row.requestFormDetailList?.length > 0) { - editFormRef.value?.fillForm?.( - JSON.parse(row.descJson || '{}'), - row.requestFormDetailList, - row.requestFormId - ); - } + // fillForm 由 SurgeryForm 内部 editData watcher 在 getList 完成后自动调用 }; const handleEditSubmitOk = async () => { diff --git a/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue b/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue index 1c0926ee8..c38335de2 100755 --- a/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue +++ b/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/applicationForm/surgery.vue @@ -356,6 +356,7 @@ let surgeryRecordsCache = null; // 原始 API 记录 let surgeryMappedCache = null; // 映射后的 el-transfer 数据 let doctorCache = null; // 医生列表(含默认主刀医生 ID) const transferRef = ref(null); +const listLoaded = ref(false); // 手术项目列表是否已加载完成 const dbTotal = ref(0); // 数据库中的手术项目总数 const checkedCount = computed(() => transferValue.value.length); const leftPanelFormat = computed(() => ({ @@ -417,6 +418,7 @@ const getList = async (key) => { applicationList.value = surgeryMappedCache; applicationListAll.value = surgeryRecordsCache; dbTotal.value = surgeryRecordsCache.length; + listLoaded.value = true; return; } loading.value = true; @@ -436,12 +438,14 @@ const getList = async (key) => { surgeryMappedCache = applicationList.value; } loading.value = false; + listLoaded.value = true; }) .catch((e) => { console.error('手术项目加载失败:', e); applicationList.value = []; dbTotal.value = 0; loading.value = false; + listLoaded.value = true; }); }; @@ -471,7 +475,7 @@ const mapToTransferItem = (item) => ({ const fillForm = (descJson, details, formId) => { editingRequestFormId.value = formId || ''; // 回填已选手术项目到穿梭框 - const ids = (details || []).map((d) => String(d.adviceDefinitionId)); + const ids = (details || []).map((d) => String(d.activityId)); transferValue.value = ids; // 回填表单字段 if (descJson) { @@ -536,6 +540,27 @@ onMounted(() => { loadDoctorOptions(); }); +// 编辑模式:等手术项目列表加载完成后回填穿梭框 +watch(() => props.editData, (val) => { + if (!val) return; + const doFill = () => { + if (val.requestFormDetailList?.length > 0) { + fillForm( + JSON.parse(val.descJson || '{}'), + val.requestFormDetailList, + val.requestFormId + ); + } + }; + if (listLoaded.value) { + doFill(); + } else { + const unwatch = watch(listLoaded, (loaded) => { + if (loaded) { unwatch(); doFill(); } + }); + } +}, { immediate: true }); + /** * 加载字典选项 */ diff --git a/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/index.vue b/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/index.vue index 334015116..f20c53c51 100755 --- a/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/index.vue +++ b/healthlink-his-ui/src/views/inpatientDoctor/home/components/order/index.vue @@ -63,8 +63,8 @@
- 全部 - 长期 + 全部 + 长期 临时 @@ -864,7 +864,15 @@ const filterPrescriptionList = computed(() => { const pList = prescriptionList.value.filter((item) => { return ( (!therapyEnum.value || therapyEnum.value == item.therapyEnum) && - (!orderClassCode.value || orderClassCode.value == item.adviceType) && + (() => { + if (!orderClassCode.value) return true; + const code = String(orderClassCode.value); + if (code.includes('-')) { + const [aType, cCode] = code.split('-'); + return item.adviceType == aType && item.categoryCode == cCode; + } + return orderClassCode.value == item.adviceType; + })() && (!orderStatus.value || (orderStatus.value == item.statusEnum && item.requestId)) ); }); @@ -2742,16 +2750,25 @@ function calculateTotalAmount(row, index) { } // 选择框改变时的处理 +// 防止 toggleCheckboxRow 触发 @checkbox-change 导致递归 +let _groupSelectLock = false; function handleSelectionChange({ selection, row }) { + if (_groupSelectLock) return; if (!row || !selection) return; + if (!row.groupId) return; const isSelected = selection.some((item) => item.uniqueKey === row.uniqueKey); - prescriptionList.value - .filter((item) => { - return item.groupId && item.groupId == row?.groupId; - }) - .forEach((row) => { - prescriptionRef.value.toggleCheckboxRow(row, isSelected); + const siblings = prescriptionList.value.filter( + (item) => item.groupId && item.groupId == row.groupId + ); + if (siblings.length <= 1) return; + _groupSelectLock = true; + try { + siblings.forEach((sibling) => { + prescriptionRef.value.setCheckboxRow([sibling], isSelected); }); + } finally { + nextTick(() => { _groupSelectLock = false; }); + } } /** diff --git a/healthlink-his-ui/src/views/inpatientNurse/medicalOrderExecution/components/prescriptionList.vue b/healthlink-his-ui/src/views/inpatientNurse/medicalOrderExecution/components/prescriptionList.vue index 6cc79f793..5e9e04f04 100755 --- a/healthlink-his-ui/src/views/inpatientNurse/medicalOrderExecution/components/prescriptionList.vue +++ b/healthlink-his-ui/src/views/inpatientNurse/medicalOrderExecution/components/prescriptionList.vue @@ -174,8 +174,8 @@ :data="item" border :header-cell-style="{ background: '#eef9fd !important' }" - @checkbox-change="({ selection, row }) => handleRowSelect(selection, row, index)" - @checkbox-all="({ selection }) => handleSelectAll(selection, index)" + @checkbox-change="({ records, row }) => handleRowSelect(records, row, index)" + @checkbox-all="({ records }) => handleSelectAll(records, index)" > 0) { + // 刷新前保存当前选中状态,刷新后恢复(用于执行/不执行后的列表更新) + const previousSelectedIds = skipAutoSelectAll ? new Set(selectedRowIds.value) : null; loading.value = true; let encounterIds = patientInfoList.value.map((i) => i.encounterId).join(','); getPrescriptionList({ @@ -451,17 +453,21 @@ function handleGetPrescription(skipAutoSelectAll = false) { prescription.procedureIds = []; // 添加复选框状态管理 prescription.checkedRates = {}; - // 已执行时间点列表 + // 已执行时间点列表(只取日期部分,忽略时间——全局ObjectMapper的setDateFormat + // 会丢失时区导致时间部分恒为00:00:00,与前端dateStr中的HH:mm无法匹配) let exeTimeList = prescription.exePerformRecordList.map((item) => { - return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD HH:mm:ss'); + return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD'); }); + if (exeTimeList.length > 0) { + console.log('[DEBUG] requestId:', prescription.requestId, 'exeTimeList:', exeTimeList, 'raw:', prescription.exePerformRecordList.map(i => i.occurrenceTime)); + } // 不执行时间点列表 let stopTimeList = prescription.stopPerformRecordList.map((item) => { - return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD HH:mm:ss'); + return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD'); }); // 取消执行时间点列表 let cancelTimeList = prescription.cancelPerformRecordList.map((item) => { - return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD HH:mm:ss'); + return formatDateStr(item.occurrenceTime, 'YYYY-MM-DD'); }); if (rate) { // 拼成日期加全部时间点的形式,显示示例:03-01 [09:00, 10:00, 11:00] @@ -475,10 +481,12 @@ function handleGetPrescription(skipAutoSelectAll = false) { let rateItems = []; rate.forEach((rateItem) => { let dateStr = prescription.year + '-' + time + ' ' + rateItem + ':00'; + // 日期部分,用于与 exeTimeList/stopTimeList/cancelTimeList 匹配(后者只含日期,无时间) + let dateOnly = prescription.year + '-' + time; switch (props.exeStatus) { case 1: // 待执行tab - // 如果该时间点未执行并且不在不执行列表中,则加入待选中列表 - if (!exeTimeList.includes(dateStr) && !stopTimeList.includes(dateStr)) { + // 如果该日期未执行并且不在不执行列表中,则加入待选中列表 + if (!exeTimeList.includes(dateOnly) && !stopTimeList.includes(dateOnly)) { rateItems.push({ rate: rateItem, }); @@ -488,7 +496,7 @@ function handleGetPrescription(skipAutoSelectAll = false) { break; case 6: // 已执行tab let index = exeTimeList.findIndex((item) => { - return item == dateStr; + return item == dateOnly; }); if (index != -1) { // 显示执行人practitionerName @@ -504,9 +512,9 @@ function handleGetPrescription(skipAutoSelectAll = false) { break; case 5: // 不执行tab let index1 = stopTimeList.findIndex((item) => { - return item == dateStr; + return item == dateOnly; }); - if (stopTimeList.includes(dateStr)) { + if (stopTimeList.includes(dateOnly)) { // 显示执行人practitionerName rateItems.push({ practitionerName: prescription.stopPerformRecordList[index1].practitionerName, @@ -517,9 +525,9 @@ function handleGetPrescription(skipAutoSelectAll = false) { break; case 9: // 取消执行tab let index2 = cancelTimeList.findIndex((item) => { - return item == dateStr; + return item == dateOnly; }); - if (cancelTimeList.includes(dateStr)) { + if (cancelTimeList.includes(dateOnly)) { rateItems.push({ practitionerName: prescription.cancelPerformRecordList[index2].practitionerName, @@ -547,7 +555,10 @@ function handleGetPrescription(skipAutoSelectAll = false) { prescription.checkedRates = newCheckedRates; // 处理已执行记录,拿到全部的执行人id,取消执行时候要传id prescription.exePerformRecordList.forEach((item) => { - if (prescription.executeTimes.includes(item.occurrenceTime)) { + // occurrenceTime 经全局 ObjectMapper 序列化后时间部分为 00:00:00, + // 用日期部分匹配 executeTimes 中的完整时间字符串 + const occDateOnly = formatDateStr(item.occurrenceTime, 'YYYY-MM-DD'); + if (prescription.executeTimes.some((t) => t.startsWith(occDateOnly))) { prescription.procedureIds.push(item.procedureId); } }); @@ -571,8 +582,29 @@ function handleGetPrescription(skipAutoSelectAll = false) { // 将分组结果转换为数组形式 prescriptionList.value = Object.values(groupedPrescriptions); - // 默认选中全部行(执行后刷新时不自动全选,保持用户操作状态) - if (!skipAutoSelectAll) { + if (skipAutoSelectAll && previousSelectedIds) { + // 执行/不执行后刷新:只恢复父checkbox行选中,子checkbox保持未选中 + nextTick(() => { + selectedRowIds.value.clear(); + prescriptionList.value.forEach((item, index) => { + const tableRef = proxy.$refs['tableRef' + index]; + item.forEach((row) => { + if (previousSelectedIds.has(row.requestId)) { + selectedRowIds.value.add(row.requestId); + if (tableRef && tableRef[0]) { + tableRef[0].setCheckboxRow([row], true); + } + } + // 清空子checkbox选中状态,避免刷新后自动勾选 + row.checkedRates = {}; + row.executeTimes = []; + row.procedureIds = []; + }); + }); + updateChooseAllStatus(); + }); + } else { + // 初次加载或手动刷新:默认全选 nextTick(() => { defaultSelectAllRows(); }); @@ -588,7 +620,6 @@ function handleGetPrescription(skipAutoSelectAll = false) { prescriptionList.value = []; loading.value = false; }); - chooseAll.value = false; } else { prescriptionList.value = []; selectedRowIds.value.clear(); @@ -794,21 +825,17 @@ function handelSwicthChange(value) { prescriptionList.value.forEach((item, index) => { const tableRef = proxy.$refs['tableRef' + index]; if (tableRef && tableRef[0]) { - if (value) { - // 全选:选中所有行并联动checkbox - item.forEach((row) => { + // 批量设置选中/取消选中(setCheckboxRow 显式设置,比 toggleCheckboxRow 更可靠) + tableRef[0].setCheckboxRow(item, value); + item.forEach((row) => { + if (value) { selectedRowIds.value.add(row.requestId); - tableRef[0].toggleCheckboxRow(row, true); selectAllCheckboxesInRow(row); - }); - } else { - // 取消全选:取消选中所有行并联动checkbox - item.forEach((row) => { + } else { selectedRowIds.value.delete(row.requestId); - tableRef[0].toggleCheckboxRow(row, false); unselectAllCheckboxesInRow(row); - }); - } + } + }); } }); } @@ -820,10 +847,10 @@ function defaultSelectAllRows() { prescriptionList.value.forEach((item, index) => { const tableRef = proxy.$refs['tableRef' + index]; if (tableRef && tableRef[0]) { - // 选中该表格的所有行 + // 批量选中该表格的所有行(setCheckboxRow 显式设置选中状态,比 toggleCheckboxRow 更可靠) + tableRef[0].setCheckboxRow(item, true); item.forEach((row) => { selectedRowIds.value.add(row.requestId); - tableRef[0].toggleCheckboxRow(row, true); // 同时选中该行内部的所有checkbox selectAllCheckboxesInRow(row); }); @@ -904,31 +931,45 @@ function checkAndToggleRowSelection(row) { const isAllSelected = isAllCheckboxesSelected(row); const isCurrentlySelected = selectedRowIds.value.has(row.requestId); - // 根据checkbox状态更新表格行选中状态 + // 根据checkbox状态更新表格行选中状态(使用 setCheckboxRow 显式设置,避免 toggleCheckboxRow 翻转方向不确定) if (isAllSelected && !isCurrentlySelected) { selectedRowIds.value.add(row.requestId); - tableRef[0].toggleCheckboxRow(row, true); + tableRef[0].setCheckboxRow([row], true); } else if (!isAllSelected && isCurrentlySelected) { selectedRowIds.value.delete(row.requestId); - tableRef[0].toggleCheckboxRow(row, false); + tableRef[0].setCheckboxRow([row], false); } } } }); } +// 根据 requestId 从 prescriptionList 中查找原始行数据引用 +// vxe-table 事件回调传出的 row 可能是内部代理对象,直接修改其属性不会触发 Vue 响应式更新 +function findOriginalRow(requestId) { + for (const group of prescriptionList.value) { + const found = group.find((r) => r.requestId === requestId); + if (found) return found; + } + return null; +} + // 处理表格行选中事件 function handleRowSelect(selection, row, tableIndex) { + // 回查原始行引用,避免修改 vxe-table 代理对象导致 el-checkbox 不更新 + const originalRow = findOriginalRow(row.requestId); + if (!originalRow) return; + const isSelected = selection.some((item) => item.requestId === row.requestId); if (isSelected) { selectedRowIds.value.add(row.requestId); // 选中行时,选中该行内部的所有checkbox - selectAllCheckboxesInRow(row); + selectAllCheckboxesInRow(originalRow); } else { selectedRowIds.value.delete(row.requestId); // 取消选中行时,取消选中该行内部的所有checkbox - unselectAllCheckboxesInRow(row); + unselectAllCheckboxesInRow(originalRow); } // 更新全选开关状态