From 210c46313031d80749b1bc2db52970eed95e465a Mon Sep 17 00:00:00 2001 From: yangkexiang <1677036288@qq.com> Date: Thu, 16 Apr 2026 10:25:12 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dbug375:=E4=BD=8F=E9=99=A2?= =?UTF-8?q?=E5=8C=BB=E7=94=9F=E7=AB=99=E7=82=B9=E5=87=BB=E2=80=9C=E7=AD=BE?= =?UTF-8?q?=E5=8F=91=E2=80=9D=E6=8C=89=E9=92=AE=E5=90=8E=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E6=8F=90=E7=A4=BA=E8=AF=AD=E9=94=99=E8=AF=AF=EF=BC=8C=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E4=B8=BA=E2=80=9C=E4=BF=9D=E5=AD=98=E6=88=90=E5=8A=9F?= =?UTF-8?q?=E2=80=9D=E5=B9=B6=E4=B8=94=E7=AD=BE=E5=8F=91=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=9C=AA=E5=AE=9E=E7=8E=B0=E3=80=82=20bug376?= =?UTF-8?q?:=E3=80=90=E9=97=A8=E8=AF=8A=E5=8C=BB=E7=94=9F=E7=AB=99?= =?UTF-8?q?=E3=80=91=E6=A3=80=E6=9F=A5=E9=A1=B5=E7=AD=BE=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E5=8D=95=E5=88=97=E8=A1=A8=E8=BF=87=E6=BB=A4=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=EF=BC=8C=E6=98=BE=E7=A4=BA=E4=BA=86=E5=8E=86=E5=8F=B2=E6=A3=80?= =?UTF-8?q?=E6=9F=A5=E5=B0=B1=E8=AF=8A=E8=AE=B0=E5=BD=95=20bug377:?= =?UTF-8?q?=E3=80=90=E9=97=A8=E8=AF=8A=E5=8C=BB=E7=94=9F=E7=AB=99=E3=80=91?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E7=94=B3=E8=AF=B7=E5=8D=95=E2=80=9C=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E7=A7=91=E5=AE=A4=E2=80=9D=E6=9C=AA=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E9=BB=98=E8=AE=A4=E5=80=BC=E4=B8=94=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E4=BA=A4=E4=BA=92=E9=80=BB=E8=BE=91=E4=B8=8D=E8=A7=84?= =?UTF-8?q?=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../check/controller/ExamApplyController.java | 25 ++++- .../DoctorStationAdviceAppServiceImpl.java | 3 +- .../impl/DoctorStationMainAppServiceImpl.java | 13 ++- .../impl/AdviceManageAppServiceImpl.java | 18 ++-- .../examination/examinationApplication.vue | 91 ++++++++++++++++++- .../prescription/prescriptionlist.vue | 19 ++++ .../register/components/accomplishList.vue | 2 +- .../charge/register/components/awaitList.vue | 2 +- .../register/components/registerForm.vue | 22 ++--- .../home/components/order/index.vue | 13 ++- 10 files changed, 179 insertions(+), 29 deletions(-) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/ExamApplyController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/ExamApplyController.java index 93e95050..4e857d57 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/ExamApplyController.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/controller/ExamApplyController.java @@ -64,10 +64,29 @@ public class ExamApplyController extends BaseController { * 查询检查申请单列表 */ @GetMapping("/list") - public TableDataInfo list(ExamApply examApply) { + public TableDataInfo list(ExamApply examApply, @RequestParam(value = "encounterId", required = false) Long encounterId) { startPage(); LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - if (examApply.getVisitNo() != null) { + + // 优先按本次就诊 encounterId 过滤(通过 wor_service_request 关联) + if (encounterId != null) { + List reqList = serviceRequestService.list(new LambdaQueryWrapper() + .eq(ServiceRequest::getEncounterId, encounterId) + .eq(ServiceRequest::getBasedOnTable, "exam_apply") + .isNotNull(ServiceRequest::getBasedOnId) + ); + List basedOnIds = reqList.stream() + .map(ServiceRequest::getBasedOnId) + .filter(java.util.Objects::nonNull) + .distinct() + .toList(); + // 没有本次就诊的检查申请单时,直接返回空列表 + if (basedOnIds.isEmpty()) { + return getDataTable(java.util.Collections.emptyList()); + } + wrapper.in(ExamApply::getId, basedOnIds); + } else if (examApply.getVisitNo() != null) { + // 兼容旧逻辑:按 visitNo 查询(可能包含历史记录) wrapper.eq(ExamApply::getVisitNo, examApply.getVisitNo()); } wrapper.orderByDesc(ExamApply::getApplyTime); @@ -147,6 +166,8 @@ public class ExamApplyController extends BaseController { examApply.setOperatorId("system"); } examApplyService.save(examApply); + // 业务主键为 apply_no,自增 id 不会随 save 回填;列表接口依赖 wor_service_request.based_on_id=exam_apply.id 关联本次就诊,此处必须回读 id + examApply = examApplyService.getById(applyNo); // ========== 2. 批量保存明细 + 写入门诊医嘱 + 写入费用项 ========== if (dto.getItems() != null && !dto.getItems().isEmpty()) { diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java index 5641fc03..f2769e23 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationAdviceAppServiceImpl.java @@ -612,13 +612,14 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp || e.getAdviceType() == 4) // 前端耗材类型值为4 .collect(Collectors.toList()); - // 诊疗活动(前端adviceType=3诊疗、adviceType=5会诊、adviceType=6手术、adviceType=23检查 → 都属于诊疗后端分类) + // 诊疗活动(前端adviceType=3诊疗、adviceType=5会诊、adviceType=6手术、adviceType=23检查、adviceType=26护理 → 都属于诊疗后端分类) List activityList = adviceSaveList.stream() .filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType()) || e.getAdviceType() == 3 // 前端诊疗类型值为3 || e.getAdviceType() == 5 // 前端会诊类型值为5 || e.getAdviceType() == 6 // 前端手术类型值为6 || e.getAdviceType() == 23 // 前端检查类型值为23 + || e.getAdviceType() == 26 // 前端护理类型值为26 || ItemType.SURGERY.getValue().equals(e.getAdviceType())) // 后端手术类型值为6 .collect(Collectors.toList()); diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java index 75a1010d..353d75a3 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/DoctorStationMainAppServiceImpl.java @@ -147,12 +147,19 @@ public class DoctorStationMainAppServiceImpl implements IDoctorStationMainAppSer return R.fail("已接诊,请勿重复点击,已为您刷新"); } + // 允许从「待诊/暂离/诊毕」重新接诊(用于队列弹窗的完诊患者重新进入在诊) + Date now = new Date(); int update = encounterMapper.update(null, new LambdaUpdateWrapper().eq(Encounter::getId, encounterId) - .eq(Encounter::getStatusEnum, EncounterStatus.PLANNED.getValue()) // 只更新待诊状态的患者 - .set(Encounter::getReceptionTime, new Date()) + .in(Encounter::getStatusEnum, + EncounterStatus.PLANNED.getValue(), + EncounterStatus.ON_HOLD.getValue(), + EncounterStatus.DISCHARGED.getValue()) + .set(Encounter::getReceptionTime, now) + .set(Encounter::getEndTime, null) .set(Encounter::getStatusEnum, EncounterStatus.IN_PROGRESS.getValue()) - .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.RECEIVING_CARE.getValue())); + .set(Encounter::getSubjectStatusEnum, EncounterSubjectStatus.RECEIVING_CARE.getValue()) + .set(Encounter::getUpdateTime, now)); // 如果更新失败,说明状态已被其他医生修改 if (update <= 0) { diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/appservice/impl/AdviceManageAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/appservice/impl/AdviceManageAppServiceImpl.java index 3d0663df..4ef22abb 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/appservice/impl/AdviceManageAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/regdoctorstation/appservice/impl/AdviceManageAppServiceImpl.java @@ -180,9 +180,11 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService { // 药品 List medicineList = regAdviceSaveList.stream() .filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())).collect(Collectors.toList()); - // 诊疗活动 + // 诊疗活动(包含护理adviceType=26) List activityList = regAdviceSaveList.stream() - .filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())).collect(Collectors.toList()); + .filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType()) + || (e.getAdviceType() != null && e.getAdviceType() == 26)) + .collect(Collectors.toList()); // 耗材 🔧 Bug #147 修复 List deviceList = regAdviceSaveList.stream() .filter(e -> ItemType.DEVICE.getValue().equals(e.getAdviceType())).collect(Collectors.toList()); @@ -844,9 +846,11 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService { .filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())).collect(Collectors.toList()); List medicineRequestIds = medicineList.stream().map(AdviceBatchOpParam::getRequestId).collect(Collectors.toList()); - // 诊疗 + // 诊疗(包含护理adviceType=26) List activityList = paramList.stream() - .filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())).collect(Collectors.toList()); + .filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType()) + || (e.getAdviceType() != null && e.getAdviceType() == 26)) + .collect(Collectors.toList()); List activityRequestIds = activityList.stream().map(AdviceBatchOpParam::getRequestId).collect(Collectors.toList()); // 查询已完成的药品请求 @@ -902,9 +906,11 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService { .filter(e -> ItemType.MEDICINE.getValue().equals(e.getAdviceType())).collect(Collectors.toList()); List medicineRequestIds = medicineList.stream().map(AdviceBatchOpParam::getRequestId).collect(Collectors.toList()); - // 诊疗 + // 诊疗(包含护理adviceType=26) List activityList = paramList.stream() - .filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType())).collect(Collectors.toList()); + .filter(e -> ItemType.ACTIVITY.getValue().equals(e.getAdviceType()) + || (e.getAdviceType() != null && e.getAdviceType() == 26)) + .collect(Collectors.toList()); List activityRequestIds = activityList.stream().map(AdviceBatchOpParam::getRequestId).collect(Collectors.toList()); if (!medicineRequestIds.isEmpty()) { diff --git a/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue b/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue index aba3cc35..80df2adf 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/examination/examinationApplication.vue @@ -116,7 +116,29 @@ - + + + + @@ -383,6 +405,11 @@ const activeNames = ref([]); // 当前展开的折叠项 const allMethods = ref([]); +// ====== 科室下拉(来源:科室管理)====== +const orgLoading = ref(false); +const orgOptions = ref([]); // { label, value } +const orgFilteredOptions = ref([]); // 展示用(截断前200条) + // 加载所有检查方法 async function loadAllMethods() { try { @@ -408,10 +435,61 @@ async function loadAllMethods() { } onMounted(async () => { + await loadOrgOptions(); await loadAllMethods(); await loadCategoryList(); }); +async function loadOrgOptions() { + orgLoading.value = true; + try { + const res = await request({ + url: '/base-data-manage/organization/organization', + method: 'get', + }); + const records = res?.data?.records || res?.data || []; + + const flat = []; + const walk = (nodes) => { + if (!Array.isArray(nodes)) return; + for (const n of nodes) { + if (!n) continue; + // 约定:typeEnum=2 为科室;若没有 typeEnum 也兜底收集 + if (n.name && (n.typeEnum === 2 || n.typeEnum === '2' || n.typeEnum == null)) { + flat.push({ label: n.name, value: n.name }); + } + if (Array.isArray(n.children) && n.children.length > 0) walk(n.children); + } + }; + walk(records); + + // 去重 + 排序 + const uniq = Array.from(new Map(flat.map(o => [o.value, o])).values()) + .filter(o => o?.value) + .sort((a, b) => (a.label || '').localeCompare(b.label || '', 'zh-CN')); + + orgOptions.value = uniq; + orgFilteredOptions.value = uniq.slice(0, 200); + } catch (e) { + console.error('加载科室列表失败', e); + orgOptions.value = []; + orgFilteredOptions.value = []; + } finally { + orgLoading.value = false; + } +} + +function handleOrgRemoteSearch(keyword) { + const key = (keyword || '').trim().toLowerCase(); + if (!key) { + orgFilteredOptions.value = orgOptions.value.slice(0, 200); + return; + } + orgFilteredOptions.value = orgOptions.value + .filter((o) => (o.label || '').toLowerCase().includes(key)) + .slice(0, 200); +} + // 动态可用的检查方法(根据已选部位所属的检查类型进行过滤) const normalizeTypeValue = value => String(value ?? '').trim().toLowerCase(); @@ -497,6 +575,8 @@ async function loadCategoryList() { orgType: t.type, // 保存 type 用于后备匹配 typeName: t.name, // 保存 name categoryName: t.name, + // “检查类型管理”里配置的执行科室(图三) + performDeptName: t.department || '', items: [] }); } @@ -591,7 +671,8 @@ function getList() { request({ url: '/exam/apply/list', method: 'get', - params: { visitNo: props.patientInfo?.visitNo || '' } + // 默认只展示本次就诊(encounterId)产生的检查申请单 + params: { encounterId: props.patientInfo?.encounterId || '' } }).then(res => { applicationList.value = res.rows || res.data || []; }).catch(err => console.error('获取申请单列表失败', err)) @@ -705,6 +786,12 @@ function handleItemSelect(checked, item, cat) { nationalCode: item.nationalCode || '', checked: true }); + + // 自动回填执行科室:按检查项目类型 → 检查类型管理里配置的执行科室 + // 仅在未手动选择时自动填充,避免覆盖用户输入 + if (!form.performDeptCode && cat?.performDeptName) { + form.performDeptCode = cat.performDeptName; + } } else { const idx = selectedItems.value.findIndex(s => s.id === item.id); if (idx > -1) selectedItems.value.splice(idx, 1); diff --git a/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue b/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue index ba2a5f14..f8463ac5 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/prescription/prescriptionlist.vue @@ -2272,7 +2272,26 @@ function handleNumberClick(item, index, row) { // 选择执行科室处理 function handleOrgChange(value, index, row) { + // 这里的“执行科室”在后端通常以 organizationId / positionId 参与业务校验; + // 列表展示用的是 positionName,因此需要同步写入名称,避免“选了但显示空”的问题。 + row.orgId = value; row.positionId = value; + row.positionName = findOrgNameById(value) || row.positionName || ''; +} + +function findOrgNameById(id) { + if (!id) return ''; + const targetId = String(id); + const stack = Array.isArray(organization.value) ? [...organization.value] : []; + while (stack.length > 0) { + const node = stack.shift(); + if (!node) continue; + if (String(node.id) === targetId) return node.name || ''; + if (Array.isArray(node.children) && node.children.length > 0) { + stack.unshift(...node.children); + } + } + return ''; } /** diff --git a/openhis-ui-vue3/src/views/inHospitalManagement/charge/register/components/accomplishList.vue b/openhis-ui-vue3/src/views/inHospitalManagement/charge/register/components/accomplishList.vue index 0247e2c7..b6e087e1 100644 --- a/openhis-ui-vue3/src/views/inHospitalManagement/charge/register/components/accomplishList.vue +++ b/openhis-ui-vue3/src/views/inHospitalManagement/charge/register/components/accomplishList.vue @@ -67,7 +67,7 @@ { - if (newVal && newVal.length > 0 && !submitForm.medTypeCode) { - submitForm.medTypeCode = newVal[0].value; - } - }, - { immediate: true } -); - const emits = defineEmits([]); const props = defineProps({ patientInfo: { @@ -351,6 +340,17 @@ const submitForm = reactive({ ambDiagnosisName: props.inHospitalInfo.ambDiagnosisName, medTypeCode: '', // 从字典动态获取默认值 }); + +// 监听诊断类别字典加载,默认选择第一项 +watch( + med_type, + (newVal) => { + if (newVal && newVal.length > 0 && !submitForm.medTypeCode) { + submitForm.medTypeCode = newVal[0].value; + } + }, + { immediate: true } +); // /* 科室 病区 */ // watch( // () => submitForm.inDocterWorkGroupCode, diff --git a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue index 8ba5f1fb..b0d09dd7 100644 --- a/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue +++ b/openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue @@ -833,7 +833,16 @@ function handleSave() { isAdding.value = false; expandOrder.value = []; } - let saveList = prescriptionList.value.filter((item) => { + + const selectedRows = prescriptionRef.value ? prescriptionRef.value.getSelectionRows() : []; + let sourceList = []; + if (selectedRows.length > 0) { + sourceList = selectedRows; + } else { + sourceList = prescriptionList.value; + } + + let saveList = sourceList.filter((item) => { return item.statusEnum == 1; }); @@ -907,7 +916,7 @@ function handleSave() { }) .then((res) => { if (res.code === 200) { - proxy.$modal.msgSuccess('保存成功'); + proxy.$modal.msgSuccess('签发成功'); isSaving.value = false; getListInfo(false); bindMethod.value = {};