From 91a0b486626b79aae6683f3b5fd913476586ffb0 Mon Sep 17 00:00:00 2001 From: chenqi Date: Thu, 26 Mar 2026 18:22:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(consultation):=20=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E4=BC=9A=E8=AF=8A=E6=B5=81=E7=A8=8B=E4=B8=AD=E7=9A=84=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E5=8A=9F=E8=83=BD=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 deptappthoursManage.js 中添加 status 参数以仅获取已启动的机构 - 为 consultationapplication 组件添加已确认和已签名状态选项 - 扩展操作列宽度并添加打印功能按钮 - 优化 handlePrint 方法以支持行参数和性别枚举转换 - 为 consultationconfirmation 组件添加必填验证和编辑权限控制 - 修复会诊确认医师信息回显逻辑 - 在 inspectionApplication 组件中修复表格行点击事件和检验项目加载 - 禁用非紧急标记的编辑权限以解决Bug #268 - 为 surgeryApplication 组件添加响应码验证和错误处理 - 在 consultation 组件中添加表单验证清除功能 - 为 PackageManagement 组件实现动态机构选项加载 - 重构 PackageSettings 组件的套餐金额显示和只读模式 - 为检查项目设置组件添加套餐筛选和下级类型选择功能 - 实现检验套餐的编辑和查看模式切换功能 --- .../impl/DoctorScheduleAppServiceImpl.java | 6 +- .../appservice/ICheckMethodAppService.java | 2 +- .../appservice/ICheckPartAppService.java | 2 +- .../impl/CheckMethodAppServiceImpl.java | 19 +- .../impl/CheckPackageAppServiceImpl.java | 73 ++++---- .../impl/CheckPartAppServiceImpl.java | 18 +- .../impl/SurgicalScheduleAppServiceImpl.java | 28 ++- .../RequestFormManageAppMapper.xml | 3 + .../appoinmentmanage/deptappthoursManage.js | 3 +- .../consultationapplication/index.vue | 35 ++-- .../consultationconfirmation/index.vue | 40 ++-- .../doctorstation/components/consultation.vue | 18 ++ .../inspection/inspectionApplication.vue | 143 +++++++++------ .../components/surgery/surgeryApplication.vue | 32 ++-- .../Inspection/PackageManagement.vue | 49 ++++- .../views/maintainSystem/Inspection/index.vue | 122 +++++++++---- .../components/PackageManagement.vue | 39 +++- .../components/PackageSettings.vue | 171 ++++++++++-------- .../checkprojectSettings/index.vue | 13 +- .../src/views/surgicalschedule/index.vue | 81 ++++++++- 20 files changed, 631 insertions(+), 266 deletions(-) diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java index d9631ac1..51b6fdb4 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java @@ -260,7 +260,10 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService { || doctorSchedule.getLimitNumber() != null || doctorSchedule.getStopReason() != null || doctorSchedule.getRegType() != null - || doctorSchedule.getRegisterFee() != null; + || doctorSchedule.getRegisterFee() != null + || doctorSchedule.getRegisterItem() != null + || doctorSchedule.getDiagnosisItem() != null + || doctorSchedule.getDiagnosisFee() != null; if (needSyncPool) { schedulePoolService.lambdaUpdate() @@ -277,6 +280,7 @@ public class DoctorScheduleAppServiceImpl implements IDoctorScheduleAppService { .set(doctorSchedule.getRegisterFee() != null, SchedulePool::getFee, Double.valueOf(doctorSchedule.getRegisterFee().toString())) .set(doctorSchedule.getRegisterFee() != null, SchedulePool::getInsurancePrice, Double.valueOf(doctorSchedule.getRegisterFee().toString())) + .set(doctorSchedule.getRegisterItem() != null, SchedulePool::getRegType, doctorSchedule.getRegisterItem()) .update(); } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckMethodAppService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckMethodAppService.java index 37582307..8c5cd782 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckMethodAppService.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckMethodAppService.java @@ -24,5 +24,5 @@ public interface ICheckMethodAppService{ R searchCheckMethodList(Integer pageNo, Integer pageSize, String checkType, String name, String packageName); - R exportCheckMethod(String checkType, String name, String packageName, HttpServletResponse response); + void exportCheckMethod(String checkType, String name, String packageName, HttpServletResponse response); } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckPartAppService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckPartAppService.java index 150a1710..ce58cad8 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckPartAppService.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/ICheckPartAppService.java @@ -16,5 +16,5 @@ public interface ICheckPartAppService { R searchCheckPartList(Integer pageNo, Integer pageSize, String checkType, String name, String packageName); - R exportCheckPart(String checkType, String name, String packageName, HttpServletResponse response); + void exportCheckPart(String checkType, String name, String packageName, HttpServletResponse response); } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckMethodAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckMethodAppServiceImpl.java index e315c582..8f8d3fac 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckMethodAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckMethodAppServiceImpl.java @@ -89,7 +89,7 @@ public class CheckMethodAppServiceImpl implements ICheckMethodAppService { } @Override - public R exportCheckMethod(String checkType, String name, String packageName, HttpServletResponse response) { + public void exportCheckMethod(String checkType, String name, String packageName, HttpServletResponse response) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); if (checkType != null && ObjectUtil.isNotEmpty(checkType)) { wrapper.eq(CheckMethod::getCheckType, checkType); @@ -103,7 +103,13 @@ public class CheckMethodAppServiceImpl implements ICheckMethodAppService { List list = checkMethodService.list(wrapper); if (list.isEmpty()) { - return R.fail("导出Excel失败,无数据。"); + try { + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write("{\"code\":500,\"msg\":\"导出Excel失败,无数据。\"}"); + } catch (IOException e) { + log.error("写入响应失败", e); + } + return; } try { @@ -123,9 +129,12 @@ public class CheckMethodAppServiceImpl implements ICheckMethodAppService { ExcelFillerUtil.makeExcelFile(response, list, headers, excelName, null); } catch (IOException | IllegalAccessException e) { log.error("导出Excel失败", e); - return R.fail("导出Excel失败:" + e.getMessage()); + try { + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write("{\"code\":500,\"msg\":\"导出Excel失败:" + e.getMessage() + "\"}"); + } catch (IOException ex) { + log.error("写入响应失败", ex); + } } - - return R.ok(null, "导出Excel成功"); } } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPackageAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPackageAppServiceImpl.java index 9a6d8a9b..da96306c 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPackageAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPackageAppServiceImpl.java @@ -22,7 +22,7 @@ import java.util.List; import java.util.stream.Collectors; /** - * 检查套餐AppService实现 + * 检查套餐 AppService 实现 * * @author system * @date 2025-11-26 @@ -35,6 +35,32 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { private final ICheckPackageService checkPackageService; private final ICheckPackageDetailService checkPackageDetailService; + /** + * 转换明细 DTO 列表为实体列表 + * @param detailDtos 明细 DTO 列表 + * @param packageId 套餐 ID + * @param orderNumStart 起始序号 + * @return 明细实体列表 + */ + private List convertToDetails(List detailDtos, Long packageId, int orderNumStart) { + if (detailDtos == null || detailDtos.isEmpty()) { + return new ArrayList<>(); + } + + List details = new ArrayList<>(); + int orderNum = orderNumStart; + for (CheckPackageDetailDto detailDto : detailDtos) { + CheckPackageDetail detail = new CheckPackageDetail(); + BeanUtils.copyProperties(detailDto, detail); + detail.setPackageId(packageId); + detail.setOrderNum(orderNum++); + detail.setCreateTime(LocalDateTime.now()); + detail.setUpdateTime(LocalDateTime.now()); + details.add(detail); + } + return details; + } + @Override public R getCheckPackageList() { try { @@ -61,7 +87,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { .orderByAsc(CheckPackageDetail::getOrderNum) ); - // 转换为DTO + // 转换为 DTO CheckPackageDto dto = new CheckPackageDto(); BeanUtils.copyProperties(checkPackage, dto); @@ -101,17 +127,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { // 保存套餐明细 if (checkPackageDto.getItems() != null && !checkPackageDto.getItems().isEmpty()) { - List details = new ArrayList<>(); - int orderNum = 1; - for (CheckPackageDetailDto detailDto : checkPackageDto.getItems()) { - CheckPackageDetail detail = new CheckPackageDetail(); - BeanUtils.copyProperties(detailDto, detail); - detail.setPackageId(checkPackage.getId()); - detail.setOrderNum(orderNum++); - detail.setCreateTime(LocalDateTime.now()); - detail.setUpdateTime(LocalDateTime.now()); - details.add(detail); - } + List details = convertToDetails(checkPackageDto.getItems(), checkPackage.getId(), 1); checkPackageDetailService.saveBatch(details); } @@ -119,10 +135,10 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { } catch (Exception e) { log.error("新增检查套餐失败", e); - // 捕获PostgreSQL唯一约束冲突异常 + // 捕获 PostgreSQL 唯一约束冲突异常 String errorMessage = e.getMessage(); if (errorMessage != null) { - // PostgreSQL唯一约束错误通常包含 "duplicate key value" 或约束名称 + // PostgreSQL 唯一约束错误通常包含 "duplicate key value" 或约束名称 if (errorMessage.contains("duplicate key value") || errorMessage.contains("违反唯一约束") || errorMessage.contains("unique constraint")) { @@ -135,7 +151,7 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { } } - return R.fail("新增检查套餐失败: " + errorMessage); + return R.fail("新增检查套餐失败:" + errorMessage); } } @@ -170,24 +186,14 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { // 保存新的套餐明细 if (checkPackageDto.getItems() != null && !checkPackageDto.getItems().isEmpty()) { - List details = new ArrayList<>(); - int orderNum = 1; - for (CheckPackageDetailDto detailDto : checkPackageDto.getItems()) { - CheckPackageDetail detail = new CheckPackageDetail(); - BeanUtils.copyProperties(detailDto, detail); - detail.setPackageId(checkPackage.getId()); - detail.setOrderNum(orderNum++); - detail.setCreateTime(LocalDateTime.now()); - detail.setUpdateTime(LocalDateTime.now()); - details.add(detail); - } + List details = convertToDetails(checkPackageDto.getItems(), checkPackage.getId(), 1); checkPackageDetailService.saveBatch(details); } return R.ok("更新成功"); } catch (Exception e) { log.error("更新检查套餐失败", e); - return R.fail("更新检查套餐失败: " + e.getMessage()); + return R.fail("更新检查套餐失败:" + e.getMessage()); } } @@ -201,11 +207,14 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { return R.fail("套餐不存在"); } - // 删除套餐明细 - checkPackageDetailService.remove( + // 删除套餐明细 - 先删除子表数据 + boolean removeDetailsResult = checkPackageDetailService.remove( new LambdaQueryWrapper() .eq(CheckPackageDetail::getPackageId, id) ); + if (!removeDetailsResult) { + log.warn("删除套餐明细失败,套餐 ID: {}", id); + } // 删除套餐主表 boolean deleteResult = checkPackageService.removeById(id); @@ -213,11 +222,11 @@ public class CheckPackageAppServiceImpl implements ICheckPackageAppService { return R.fail("删除套餐失败"); } + log.info("删除检查套餐成功,套餐 ID: {}", id); return R.ok("删除成功"); } catch (Exception e) { log.error("删除检查套餐失败", e); - return R.fail("删除检查套餐失败: " + e.getMessage()); + return R.fail("删除检查套餐失败:" + e.getMessage()); } } } - diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPartAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPartAppServiceImpl.java index cfde418b..b0686a57 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPartAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/check/appservice/impl/CheckPartAppServiceImpl.java @@ -65,7 +65,7 @@ public class CheckPartAppServiceImpl implements ICheckPartAppService { } @Override - public R exportCheckPart(String checkType, String name, String packageName, HttpServletResponse response) { + public void exportCheckPart(String checkType, String name, String packageName, HttpServletResponse response) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); if (checkType != null && ObjectUtil.isNotEmpty(checkType)) { wrapper.eq(CheckPart::getCheckType, checkType); @@ -79,7 +79,13 @@ public class CheckPartAppServiceImpl implements ICheckPartAppService { List list = checkPartService.list(wrapper); if (list.isEmpty()) { - return R.fail("导出Excel失败,无数据。"); + try { + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write("{\"code\":500,\"msg\":\"导出Excel失败,无数据。\"}"); + } catch (IOException e) { + log.error("写入响应失败", e); + } + return; } try { @@ -102,8 +108,12 @@ public class CheckPartAppServiceImpl implements ICheckPartAppService { ExcelFillerUtil.makeExcelFile(response, list, headers, excelName, null); } catch (IOException | IllegalAccessException e) { log.error("导出Excel失败", e); - return R.fail("导出Excel失败:" + e.getMessage()); + try { + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write("{\"code\":500,\"msg\":\"导出Excel失败:" + e.getMessage() + "\"}"); + } catch (IOException ex) { + log.error("写入响应失败", ex); + } } - return R.ok(null, "导出Excel成功"); } } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgicalScheduleAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgicalScheduleAppServiceImpl.java index 6cf68292..4e093c9c 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgicalScheduleAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgicalScheduleAppServiceImpl.java @@ -1,5 +1,6 @@ package com.openhis.web.clinicalmanage.appservice.impl; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.core.common.core.domain.R; @@ -7,6 +8,8 @@ import com.core.common.core.domain.model.LoginUser; import com.core.common.utils.SecurityUtils; import com.openhis.administration.domain.Patient; import com.openhis.administration.service.IPatientService; +import com.openhis.clinical.domain.Surgery; +import com.openhis.clinical.service.ISurgeryService; import com.openhis.surgicalschedule.domain.OpSchedule; import com.openhis.surgicalschedule.service.IOpScheduleService; import com.openhis.web.clinicalmanage.appservice.ISurgicalScheduleAppService; @@ -47,6 +50,9 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi @Resource private SurgicalScheduleAppMapper surgicalScheduleAppMapper; + @Resource + private ISurgeryService surgeryService; + @Resource private RequestFormManageAppMapper requestFormManageAppMapper; @@ -183,12 +189,30 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi // 保存手术安排 boolean saved = opScheduleService.save(opSchedule); - //修改申请单状态为已排期 - if (!saved) { return R.fail("新增手术安排失败"); } + // Bug #247 修复:更新手术申请单状态为已排期 (1) + if (opCreateScheduleDto.getApplyId() != null) { + try { + // 通过手术单号查找手术申请记录并更新状态 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(com.openhis.clinical.domain.Surgery::getSurgeryNo, opSchedule.getOperCode()) + .eq(com.openhis.clinical.domain.Surgery::getDeleteFlag, "0"); + com.openhis.clinical.domain.Surgery surgery = surgeryService.getOne(queryWrapper); + if (surgery != null) { + surgery.setStatusEnum(1); // 1 = 已排期 + surgery.setUpdateTime(new Date()); + surgeryService.updateById(surgery); + log.info("更新手术申请单状态为已排期 - surgeryNo: {}, surgeryId: {}", opSchedule.getOperCode(), surgery.getId()); + } + } catch (Exception e) { + log.error("更新手术申请单状态失败 - operCode: {}", opSchedule.getOperCode(), e); + // 状态更新失败不影响主流程,只记录日志 + } + } + return R.ok("新增手术安排成功"); } diff --git a/openhis-server-new/openhis-application/src/main/resources/mapper/regdoctorstation/RequestFormManageAppMapper.xml b/openhis-server-new/openhis-application/src/main/resources/mapper/regdoctorstation/RequestFormManageAppMapper.xml index 411ccf22..d9c80ca5 100644 --- a/openhis-server-new/openhis-application/src/main/resources/mapper/regdoctorstation/RequestFormManageAppMapper.xml +++ b/openhis-server-new/openhis-application/src/main/resources/mapper/regdoctorstation/RequestFormManageAppMapper.xml @@ -85,6 +85,7 @@ cs.apply_dept_id, cs.apply_dept_name, cs.surgery_type_enum, + cs.status_enum, fc.contract_name AS fee_type FROM doc_request_form drf LEFT JOIN cli_surgery cs ON cs.surgery_no = drf.prescription_no @@ -106,6 +107,8 @@ AND cs.apply_dept_id = #{requestFormDto.applyDeptId} AND drf.delete_flag = '0' + + AND (cs.status_enum IS NULL OR cs.status_enum != 4) ORDER BY drf.create_time DESC diff --git a/openhis-ui-vue3/src/api/appoinmentmanage/deptappthoursManage.js b/openhis-ui-vue3/src/api/appoinmentmanage/deptappthoursManage.js index 4a87a288..577110e4 100644 --- a/openhis-ui-vue3/src/api/appoinmentmanage/deptappthoursManage.js +++ b/openhis-ui-vue3/src/api/appoinmentmanage/deptappthoursManage.js @@ -70,7 +70,8 @@ export function getTenantList() { method: 'get', params: { pageNum: 1, - pageSize: 1000 + pageSize: 1000, + status: '1' // 只获取已启动的机构 (1=已启动,0=未启动) } }) } diff --git a/openhis-ui-vue3/src/views/consultationmanagement/consultationapplication/index.vue b/openhis-ui-vue3/src/views/consultationmanagement/consultationapplication/index.vue index 052a4d3c..165d72f2 100644 --- a/openhis-ui-vue3/src/views/consultationmanagement/consultationapplication/index.vue +++ b/openhis-ui-vue3/src/views/consultationmanagement/consultationapplication/index.vue @@ -69,6 +69,8 @@ + + @@ -137,8 +139,15 @@ - + + - 收费 + + 收费 - 退费 + + 退费 - 执行 + + 执行 @@ -1521,62 +1527,87 @@ function handleDelete(row) { function handleCellClick(row, column) { // 点击表格行时,将该申请单的数据加载到表单中 if (row && row.applicationId) { - // 切换到申请单 TAB - leftActiveTab.value = 'application' - - // 加载表单数据 - Object.assign(formData, { - applicationId: row.applicationId, - applyNo: row.applyNo, - patientName: row.patientName, - medicalrecordNumber: row.medicalrecordNumber, - natureofCost: row.natureofCost || 'self', - applyTime: row.applyTime, - applyDepartment: row.applyDepartment, - applyDocName: row.applyDocName, - executeDepartment: row.executeDepartment || 'medical_lab', - clinicDesc: row.clinicDesc, - contraindication: row.contraindication, - clinicDiag: row.clinicDiag, - medicalHistorySummary: row.medicalHistorySummary, - purposeofInspection: row.purposeofInspection, - physicalExam: row.physicalExam, - applyRemark: row.applyRemark, - priorityCode: row.priorityCode || 0, - applyStatus: row.applyStatus || 1, - needRefund: row.needRefund || false, - needExecute: row.needExecute || false, - inspectionDoctor: row.inspectionDoctor, - inspectionTime: row.inspectionTime, - auditDoctor: row.auditDoctor, - auditTime: row.auditTime, - visitNo: row.visitNo, - applyDocCode: row.applyDocCode, - applyDeptCode: row.applyDeptCode, - specimenName: row.specimenName, - encounterId: row.encounterId, - patientId: row.patientId, - applyOrganizationId: row.applyOrganizationId - }) - - // 根据检验项目名称解析已选项目 - selectedInspectionItems.value = [] - 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)) { - selectedInspectionItems.value.push({ ...item }) - } - }) + loadApplicationToForm(row); + } +} + +// 🔧 Bug #269 修复:行点击事件处理 +function handleRowClick(currentRow, oldRow) { + // 点击表格行时,将该申请单的数据加载到表单中 + if (currentRow && currentRow.applicationId) { + loadApplicationToForm(currentRow); + } +} + +// 🔧 Bug #269 修复:提取公共方法加载申请单到表单 +function loadApplicationToForm(row) { + // 切换到申请单 TAB + leftActiveTab.value = 'application' + + // 加载表单数据 + Object.assign(formData, { + applicationId: row.applicationId, + applyNo: row.applyNo, + patientName: row.patientName, + medicalrecordNumber: row.medicalrecordNumber, + natureofCost: row.natureofCost || 'self', + applyTime: row.applyTime, + applyDepartment: row.applyDepartment, + applyDocName: row.applyDocName, + executeDepartment: row.executeDepartment || 'medical_lab', + clinicDesc: row.clinicDesc, + contraindication: row.contraindication, + clinicDiag: row.clinicDiag, + medicalHistorySummary: row.medicalHistorySummary, + purposeofInspection: row.purposeofInspection, + physicalExam: row.physicalExam, + applyRemark: row.applyRemark, + priorityCode: row.priorityCode || 0, + applyStatus: row.applyStatus || 0, // 🔧 Bug #268: 默认为 0 + needRefund: row.needRefund || false, + needExecute: row.needExecute || false, + inspectionDoctor: row.inspectionDoctor, + inspectionTime: row.inspectionTime, + auditDoctor: row.auditDoctor, + auditTime: row.auditTime, + visitNo: row.visitNo, + applyDocCode: row.applyDocCode, + applyDeptCode: row.applyDeptCode, + specimenName: row.specimenName, + encounterId: row.encounterId, + patientId: row.patientId, + applyOrganizationId: row.applyOrganizationId + }) + + // 🔧 Bug #269 修复:根据检验项目 ID 加载详细的检验项目数据 + selectedInspectionItems.value = [] + if (row.labApplyItemList && row.labApplyItemList.length > 0) { + // 如果后端返回了检验项目列表,直接使用 + selectedInspectionItems.value = row.labApplyItemList.map(item => ({ + ...item, + itemId: item.itemId || item.id || Math.random().toString(36).substring(2, 11), + itemName: item.itemName || item.name || '', + itemPrice: item.itemPrice || item.price || 0, + itemAmount: item.itemAmount || item.price || 0, + })) + } else 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)) { + selectedInspectionItems.value.push({ ...item }) + } }) - } - - // 重置验证错误状态 - Object.keys(validationErrors).forEach(key => { - validationErrors[key] = false }) } + + // 重置验证错误状态 + Object.keys(validationErrors).forEach(key => { + validationErrors[key] = false + }) + + console.log('已加载申请单到表单:', row.applyNo); } // 监听activeTab变化 diff --git a/openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue b/openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue index 8d0c616c..43471171 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue @@ -1048,29 +1048,37 @@ function submitForm() { if (form.value.id == undefined) { // 新增手术 addSurgery(form.value).then((res) => { - proxy.$modal.msgSuccess('新增成功') - //保存麻醉方式 - seesionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum) - open.value = false - getList() + if (res.code === 200) { + proxy.$modal.msgSuccess('新增成功') + //保存麻醉方式 + sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum) + open.value = false + getList() + } else { + proxy.$modal.msgError(res.msg || '新增手术失败') + } }).catch(error => { console.error('新增手术失败:', error) - proxy.$message.error('新增手术失败,请检查表单信息') + proxy.$modal.msgError('新增手术失败,请稍后重试') }) } else { // 修改手术 updateSurgery(form.value).then((res) => { - proxy.$modal.msgSuccess('修改成功') - seesionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum) - open.value = false - getList() + if (res.code === 200) { + proxy.$modal.msgSuccess('修改成功') + sessionStorage.setItem('anesthesiaType', form.value.anesthesiaTypeEnum) + open.value = false + getList() + } else { + proxy.$modal.msgError(res.msg || '修改手术失败') + } }).catch(error => { console.error('更新手术失败:', error) - proxy.$message.error('更新手术失败,请检查表单信息') + proxy.$modal.msgError('更新手术失败,请稍后重试') }) } } else { - proxy.$message.error('请检查表单信息,标红字段为必填项') + proxy.$modal.msgError('请检查表单信息,标红字段为必填项') } }) } diff --git a/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue b/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue index fd8c0151..17a28741 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/Inspection/PackageManagement.vue @@ -192,7 +192,7 @@ import {computed, onMounted, ref} from 'vue'; import {useRouter} from 'vue-router'; import {ElMessage} from 'element-plus'; import {getLocationTree} from '@/views/charge/outpatientregistration/components/outpatientregistration'; -import {listInspectionPackage} from '@/api/system/inspectionPackage'; +import {listInspectionPackage, delInspectionPackage} from '@/api/system/inspectionPackage'; import { getTenantPage } from '@/api/system/tenant'; @@ -583,7 +583,13 @@ const pageButtons = computed(() => { // 处理新增 function handleAdd() { - router.push('/maintainSystem/Inspection?tab=2'); + router.push({ + path: '/maintainSystem/Inspection', + query: { + tab: '2', + mode: 'add' + } + }); } // 处理编辑 @@ -625,12 +631,39 @@ function handleView(item) { } // 处理删除 -function handleDelete(item) { - if (confirm(`确定要删除套餐 "${item.name}" 吗?`)) { - const index = tableData.value.findIndex(i => i.id === item.id); - if (index !== -1) { - tableData.value.splice(index, 1); - alert(`套餐 "${item.name}" 已删除`); +async function handleDelete(item) { + try { + await ElMessageBox.confirm( + `确定要删除套餐 "${item.name}" 吗?删除后将无法恢复。`, + '确认删除', + { + confirmButtonText: '确定删除', + cancelButtonText: '取消', + type: 'warning' + } + ) + + // 获取套餐ID(优先使用 basicInformationId) + const packageId = item.basicInformationId || item.id + if (!packageId) { + ElMessage.error('无法获取套餐ID,删除失败') + return + } + + // 调用后端API删除 + const response = await delInspectionPackage(packageId) + + if (response && (response.code === 200 || response.code === 0)) { + ElMessage.success('删除成功') + // 删除成功后,重新加载列表数据 + loadData() + } else { + ElMessage.error(response?.msg || response?.message || '删除失败') + } + } catch (error) { + if (error !== 'cancel' && error !== 'close') { + console.error('删除失败:', error) + ElMessage.error('删除失败: ' + (error?.message || error?.msg || '未知错误')) } } } diff --git a/openhis-ui-vue3/src/views/maintainSystem/Inspection/index.vue b/openhis-ui-vue3/src/views/maintainSystem/Inspection/index.vue index 010b4506..b93a58e1 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/Inspection/index.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/Inspection/index.vue @@ -424,7 +424,8 @@ 重置 套餐管理 - 保存 + {{ packageMode === 'edit' ? '更新' : '保存' }} + 返回管理 @@ -448,6 +449,7 @@ default-first-option placeholder="请选择或输入套餐级别" style="width: 100%;" + :disabled="isViewMode" @change="handlePackageLevelChange" > @@ -483,7 +486,7 @@
套餐名称 - +
@@ -495,6 +498,7 @@ @change="handleTenantChange" clearable filterable + :disabled="isViewMode" :loading="loadingTenant" no-data-text="暂无数据,请稍后重试" @visible-change="handleTenantVisibleChange" @@ -513,7 +517,7 @@
折扣 % - +
制单人 @@ -521,32 +525,32 @@
备注 - +
是否停用 - + 启用 停用
显示套餐名 - +
生成服务费 - +
套餐价格 - + 启用 不启用 @@ -558,7 +562,7 @@
lis分组 - +
血量 - +
@@ -578,7 +582,7 @@
检验套餐明细
- +
@@ -890,6 +894,7 @@ import { import {listLisGroup} from '@/api/system/checkType'; import { addInspectionPackage, + updateInspectionPackage, getInspectionPackage, listInspectionPackageDetails, saveInspectionPackageDetails @@ -1545,6 +1550,12 @@ const bloodVolume = ref(''); const remarks = ref(''); // 检验套餐明细项目 - 从后端API获取 const packageItems = ref([]); +// 套餐当前模式: add-新增, edit-编辑, view-查看 +const packageMode = ref('add'); +// 当前编辑的套餐ID(用于编辑和查看模式) +const currentPackageId = ref(null); +// 是否为查看模式(只读) +const isViewMode = computed(() => packageMode.value === 'view'); let addingItem = false; const addPackageItem = () => { @@ -2651,34 +2662,50 @@ const savePackageData = async (basicInfo, detailData) => { }); try { - // 1. 先保存基本信息 - const basicResponse = await addInspectionPackage(basicInfo); - - // 检查响应码 - if (basicResponse.code !== 200) { - loading.close(); - throw new Error(basicResponse.msg || '保存基本信息失败'); + // 判断是新增还是编辑模式 + const isEditMode = packageMode.value === 'edit' && currentPackageId.value; + + // 如果是编辑模式,设置packageId到basicInfo中 + if (isEditMode) { + basicInfo.packageId = currentPackageId.value; } - - // 检查响应数据结构 - 兼容多种可能的响应格式 + + // 1. 先保存或更新基本信息 let packageId = null; + let basicResponse; + + if (isEditMode) { + // 编辑模式:调用更新API + basicResponse = await updateInspectionPackage(basicInfo); + packageId = currentPackageId.value; + } else { + // 新增模式:调用新增API + basicResponse = await addInspectionPackage(basicInfo); + + // 检查响应码 + if (basicResponse.code !== 200) { + loading.close(); + throw new Error(basicResponse.msg || '保存基本信息失败'); + } - if (basicResponse.data) { - // 标准格式:{code: 200, data: {packageId: xxx}} - packageId = basicResponse.data.packageId || basicResponse.data.id; - } else if (basicResponse.packageId) { - // 如果data不存在,尝试直接从响应根级别获取 - packageId = basicResponse.packageId; - } else if (basicResponse.id) { - // 如果data不存在,尝试直接从响应根级别获取id - packageId = basicResponse.id; - } + // 检查响应数据结构 - 兼容多种可能的响应格式 + if (basicResponse.data) { + // 标准格式:{code: 200, data: {packageId: xxx}} + packageId = basicResponse.data.packageId || basicResponse.data.id; + } else if (basicResponse.packageId) { + // 如果data不存在,尝试直接从响应根级别获取 + packageId = basicResponse.packageId; + } else if (basicResponse.id) { + // 如果data不存在,尝试直接从响应根级别获取id + packageId = basicResponse.id; + } - // 验证套餐ID是否存在 - if (!packageId) { - loading.close(); - console.error('无法从响应中获取套餐ID,完整响应:', basicResponse); - throw new Error('保存成功但未返回套餐ID。请检查后端接口是否正确返回了packageId或id字段'); + // 验证套餐ID是否存在 + if (!packageId) { + loading.close(); + console.error('无法从响应中获取套餐ID,完整响应:', basicResponse); + throw new Error('保存成功但未返回套餐ID。请检查后端接口是否正确返回了packageId或id字段'); + } } // 2. 分别保存每个明细数据到明细表,并将后端返回的 id 回填到 packageItems @@ -2780,6 +2807,10 @@ const doResetForm = () => { // 清空明细数据 packageItems.value = []; + + // 重置模式为新增 + packageMode.value = 'add'; + currentPackageId.value = null; // 重新计算金额 calculateAmounts(); @@ -2857,6 +2888,13 @@ const handlePackageManagement = () => { }); }; +const handleBackToManagement = () => { + // 返回套餐管理页面 + router.push({ + path: '/maintainSystem/Inspection/PackageManagement' + }); +}; + const refreshPage = () => { getInspectionTypeList(); }; @@ -2889,7 +2927,19 @@ watch( const applyRouteForPackage = async (query) => { const packageId = query?.packageId; - if (!packageId) return; + const mode = query?.mode || 'add'; + + // 设置当前模式和套餐ID + packageMode.value = mode; + currentPackageId.value = packageId ? String(packageId) : null; + + // 如果是新增模式,重置表单 + if (mode === 'add' || !packageId) { + activeNav.value = 2; + doResetForm(); + return; + } + activeNav.value = 2; await nextTick(); loadInspectionPackage(String(packageId)); diff --git a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue index 549f3285..fed973c4 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageManagement.vue @@ -17,8 +17,13 @@ - - + + @@ -199,6 +204,7 @@ import {ElMessage, ElMessageBox} from 'element-plus' import {getDicts} from '@/api/system/dict/data' import {listDept} from '@/api/system/dept' import {delCheckPackage, getCheckPackage, listCheckPackage} from '@/api/system/checkType' +import {getTenantPage} from '@/api/system/tenant' import request from '@/utils/request' import useUserStore from '@/store/modules/user' @@ -275,6 +281,8 @@ const loading = ref(false) const packageLevelOptions = ref([]) // 科室选项 const departments = ref([]) +// 卫生机构选项 +const organizationOptions = ref([]) // 初始化数据 onMounted(async () => { @@ -394,6 +402,33 @@ onMounted(async () => { } } + // 获取卫生机构列表 + try { + const tenantResponse = await getTenantPage({ pageNum: 1, pageSize: 100 }) + if (tenantResponse && tenantResponse.code === 200) { + const tenantData = tenantResponse.data || {} + let tenantList = [] + if (Array.isArray(tenantData)) { + tenantList = tenantData + } else if (tenantData.records) { + tenantList = tenantData.records + } else if (tenantData.rows) { + tenantList = tenantData.rows + } else if (tenantData.list) { + tenantList = tenantData.list + } + // 过滤启用的机构 + organizationOptions.value = tenantList + .filter(item => item && item.status === '0') + .map(item => ({ + value: item.tenantName || item.name || item.orgName || String(item.id), + label: item.tenantName || item.name || item.orgName || String(item.id) + })) + } + } catch (error) { + console.error('获取卫生机构列表失败:', error) + } + // 加载列表数据 handleQuery() }) diff --git a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue index 127b86ee..030fe9f2 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue @@ -87,7 +87,7 @@ - + @@ -112,73 +112,60 @@ - - - - 启用 - 停用 - - - + + + + 启用 + 停用 + + + - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + - - - - 启用 - 不启用 - - - + + + + 启用 + 不启用 + + + - - - - - + + + + + - - - - - - - - - - - + + + + +
@@ -338,7 +325,7 @@ {{ row.origin || '-' }}
- + + + + @@ -1699,6 +1707,44 @@ function getAnesthesiaName(anesMethod) { return anesthesia ? anesthesia.label : '' } +// 获取状态标签类型 +function getStatusTagType(statusEnum) { + const typeMap = { + 0: 'info', // 新开/待排期 + 1: 'warning', // 已排期 + 2: 'primary', // 手术中 + 3: 'success', // 已完成 + 4: 'danger', // 已取消 + 5: 'info' // 暂停 + } + return typeMap[statusEnum] || 'info' +} + +// 获取状态文本 +function getStatusText(statusEnum) { + const textMap = { + 0: '待排期', + 1: '已排期', + 2: '手术中', + 3: '已完成', + 4: '已取消', + 5: '暂停' + } + return textMap[statusEnum] || '未知' +} + +// 将麻醉名称映射为枚举值 +function mapAnesthesiaNameToValue(name) { + if (!name) return undefined + if (name.includes('局部')) return '1' + if (name.includes('区域')) return '2' + if (name.includes('全身') || name.includes('全麻')) return '3' + if (name.includes('脊椎')) return '4' + if (name.includes('硬膜外')) return '5' + if (name.includes('表面')) return '6' + return undefined +} + // 根据出生日期计算年龄 function calculateAge(birthDay) { if (!birthDay) return '' @@ -1731,6 +1777,37 @@ function confirmApply() { proxy.$modal.msgWarning('请先选择一条手术申请记录') return } + const selectedRow = selectedRows[0] + // 填充手术申请信息到表单 + form.surgeryNo = selectedRow.surgeryNo // 手术单号对应填入手术单号 + form.applyId=selectedRow.applyId// 手术申请 id + form.patientId = selectedRow.patientId// 患者 id + form.visitId = selectedRow.encounterId // id 对应填入就诊 id + form.operCode = selectedRow.surgeryNo // 手术单号作为手术编码 + form.operName = selectedRow.descJson.surgeryName//手术名称 + form.preoperativeDiagnosis = selectedRow.descJson?.preoperativeDiagnosis || '' + form.patientName = selectedRow.name// 患者姓名对应填入患者姓名 + form.gender = selectedRow.gender//患者性别 + form.birthDay = selectedRow.birthDay//患者出生日期 + form.age = calculateAge(selectedRow.birthDay)//计算患者年龄 + form.applyDeptName = selectedRow.applyDeptName//申请部门名称 + form.applyDoctorName = selectedRow.applyDoctorName//申请医生 + form.applyTime = selectedRow.applyTime//申请时间 + form.surgeryType = selectedRow.surgeryTypeEnum//手术类型 + form.surgeryNature = selectedRow.surgeryTypeEnum//手术性质 + form.surgeonCode = selectedRow.mainSurgeonId//主刀医生 id + form.surgeonName = selectedRow.mainSurgeonName//主刀医生姓名 + form.feeType = selectedRow.feeType//费用类别 + // Bug #252 修复:继承手术申请的麻醉方式 + if (selectedRow.descJson?.anesthesiaName) { + form.anesMethod = mapAnesthesiaNameToValue(selectedRow.descJson.anesthesiaName) + } + // Bug #253/#254 修复:继承手术申请的切口类型 + if (selectedRow.descJson?.incisionLevel) { + form.incisionType = String(selectedRow.descJson.incisionLevel) + } + showApplyDialog.value = false +} const selectedRow = selectedRows[0] // 填充手术申请信息到表单 form.surgeryNo = selectedRow.surgeryNo // 手术单号对应填入手术单号