Compare commits
43 Commits
c7f85ff20d
...
guanyu
| Author | SHA1 | Date | |
|---|---|---|---|
| d52403f269 | |||
| 2148a1b2be | |||
| 1f46c1e5a1 | |||
| 79214ee8b4 | |||
| adb088a263 | |||
| 008ae24b44 | |||
| e0554d7416 | |||
| a41222286f | |||
| 35fd33ba59 | |||
| a22418c26c | |||
| 2608c93e78 | |||
| e884c0b210 | |||
| 7e37193e85 | |||
| d4e1a22c10 | |||
| eedf104a99 | |||
| f05cc8da66 | |||
| 71013aa6d8 | |||
| 9c644a1c6d | |||
| f54a7ff825 | |||
| d64e1c753a | |||
| 55785252f6 | |||
| 5fd00011db | |||
| e2510fe0dd | |||
| d405e9cb5e | |||
| babf62083a | |||
| 68cfa48820 | |||
|
|
d47c83eec5 | ||
|
|
2915915881 | ||
| 68b92dfe31 | |||
| c9e8729d07 | |||
| 207640f4ef | |||
| 566ce61293 | |||
|
|
a04fa368b1 | ||
| f940078208 | |||
| 06363ec191 | |||
|
|
3c8d5e94a3 | ||
|
|
6f7f6dc9f5 | ||
|
|
376ddd46ff | ||
| e1ab9fba23 | |||
| f458835183 | |||
|
|
57f591e1c0 | ||
|
|
a98a03e00a | ||
| fddf1c2d03 |
425
MD/MODULE_INDEX.md
Normal file
425
MD/MODULE_INDEX.md
Normal file
@@ -0,0 +1,425 @@
|
||||
# HealthLink-HIS 代码模块索引
|
||||
|
||||
> 供 LLM 快速定位代码。每个模块列出 Controller → Service → Mapper 关键文件。
|
||||
> 最后更新: 2026-06-13 18:00 (298 个 Controller)
|
||||
|
||||
## 关键词 → 模块速查
|
||||
|
||||
| 关键词 | 后端模块 | 前端目录 |
|
||||
|---|---|---|
|
||||
| 门诊医生站/门诊医嘱/门诊处方/诊断/检查申请 | `doctorstation` | `doctorstation` |
|
||||
| 住院医生站/住院医嘱/临床医嘱/签发/停嘱 | `regdoctorstation` | `inpatientDoctor` |
|
||||
| 住院护士站/医嘱校对/医嘱执行/护理/换床 | `inhospitalnursestation` | `inpatientNurse` |
|
||||
| 挂号/门诊收费/门诊结算 | `chargemanage` | `charge` |
|
||||
| 住院收费/住院结算/预交金 | `inhospitalcharge` | `inHospitalManagement` |
|
||||
| 收费管理/计费/退费 | `paymentmanage` | `outpatientFinance` |
|
||||
| 药品/药房/药库/发药/取药 | `pharmacymanage` | `pharmacymanagement` |
|
||||
| 药房发药/门诊发药 | `pharmacyDispensarymanage` | `drug` |
|
||||
| 药库管理/库存 | `pharmacyWarehousemanage` | `medicineStorage` |
|
||||
| 库存管理/盘点/出入库 | `inventorymanage` | `medicineStorage` |
|
||||
| 物资管理/耗材 | `materialmanage` | `` |
|
||||
| 字典/数据字典/诊疗目录/基础数据 | `datadictionary` | `datadictionary` |
|
||||
| 部门/科室管理 | `departmentmanage` | `system` |
|
||||
| 卡管理/就诊卡 | `cardmanagement` | `cardmanagement` |
|
||||
| 检验/化验/标本 | `lab` | `inspection` |
|
||||
| 检查/影像/放射 | `Inspection` | `inspection` |
|
||||
| 手术/手术安排/手术申请 | `surgicalschedule` | `surgerymanage` |
|
||||
| 病历/电子病历/EMR | `emr` | `emr` |
|
||||
| 护理记录/护理评估 | `nursing` | `nursing` |
|
||||
| 分诊/排队/叫号 | `triageandqueuemanage` | `triageandqueuemanage` |
|
||||
| 医保/医保对码/医保目录 | `ybmanage` | `ybmanagement` |
|
||||
| 会诊/会诊申请 | `consultation` | `consultationmanagement` |
|
||||
| 院感/感染上报 | `infection` | `infection` |
|
||||
| 合理用药/处方审核 | `rationaldrug` | `rationaldrug` |
|
||||
| 中医/中医处方 | `tcm` | `tcm` |
|
||||
| 患者管理/患者信息 | `patientmanage` | `patientmanagement` |
|
||||
| 预约/挂号预约 | `appointmentmanage` | `appoinmentmanage` |
|
||||
| 报告/报告管理 | `reportmanage` | `` |
|
||||
| 质控/质量 | `quality` | `quality` |
|
||||
| 系统管理/用户/角色/权限 | `basicmanage` | `system` |
|
||||
| 门诊管理/门诊工作站 | `outpatientmanage` | `doctorstation` |
|
||||
| 前置手术/术前管理 | `preopmanage` | `preopmanage` |
|
||||
| 危急值 | `criticalvalue` | `criticalvalue` |
|
||||
| 抗菌药 | `antibiotic` | `antibiotic` |
|
||||
| 随访 | `followup` | `followup` |
|
||||
| request.js/请求拦截/响应拦截 | `common` | `crossmodule` |
|
||||
|
||||
## 后端模块详情
|
||||
|
||||
### `Inspection` (40 files)
|
||||
- **Controller**: `Inspection/controller/SampleCollectController.java` `Inspection/controller/ObservationDefController.java` `Inspection/controller/LabReferenceRangeController.java`
|
||||
- **AppService**: `Inspection/appservice/ISampleCollectAppManageAppService.java` `Inspection/appservice/ILisConfigManageAppService.java` `Inspection/appservice/IInstrumentManageAppService.java`
|
||||
- **ServiceImpl**: `Inspection/appservice/impl/LisConfigManageAppServiceImpl.java` `Inspection/appservice/impl/ObservationManageAppServiceImpl.java` `Inspection/appservice/impl/SpecimenManageAppServiceImpl.java`
|
||||
- **Mapper**: `Inspection/mapper/SampleCollectMapper.java` `Inspection/mapper/LisReportMapper.java` `Inspection/mapper/GroupRecMapper.java`
|
||||
- **DTO**: `Inspection/dto/SampleCollectManageDto.java` `Inspection/dto/SpecimenDefManageDto.java` `Inspection/dto/InstrumentManageDto.java` `Inspection/dto/LisConfigManageDto.java` `Inspection/dto/InstrumentSelParam.java`
|
||||
|
||||
### `adjustprice` (10 files)
|
||||
- **Controller**: `adjustprice/controller/ChangePriceController.java` `adjustprice/controller/ChangePriceDataListPageController.java`
|
||||
- **ServiceImpl**: `adjustprice/appservice/impl/AdjustPriceServiceImpl.java`
|
||||
- **Mapper**: `adjustprice/mapper/AdjustPriceMapper.java`
|
||||
- **DTO**: `adjustprice/dto/ChangePriceDataDto.java` `adjustprice/dto/AdjustPriceManagerSearchParam.java` `adjustprice/dto/ChangePricePageDto.java`
|
||||
|
||||
### `anesthesia` (4 files)
|
||||
- **Controller**: `anesthesia/controller/AnesthesiaController.java` `anesthesia/controller/AnesthesiaEnhancedController.java`
|
||||
- **AppService**: `anesthesia/appservice/IAnesthesiaAppService.java`
|
||||
- **ServiceImpl**: `anesthesia/appservice/impl/AnesthesiaAppServiceImpl.java`
|
||||
|
||||
### `antibiotic` (3 files)
|
||||
- **Controller**: `antibiotic/controller/AntibioticController.java`
|
||||
- **AppService**: `antibiotic/appservice/IAntibioticAppService.java`
|
||||
- **ServiceImpl**: `antibiotic/appservice/impl/AntibioticAppServiceImpl.java`
|
||||
|
||||
### `appointmentmanage` (29 files)
|
||||
- **Controller**: `appointmentmanage/controller/ScheduleSlotController.java` `appointmentmanage/controller/DeptAppthoursController.java` `appointmentmanage/controller/SchedulePoolController.java`
|
||||
- **AppService**: `appointmentmanage/appservice/IDeptAppService.java` `appointmentmanage/appservice/IDoctorScheduleAppService.java` `appointmentmanage/appservice/IClinicRoomAppService.java`
|
||||
- **ServiceImpl**: `appointmentmanage/appservice/impl/DoctorScheduleAppServiceImpl.java` `appointmentmanage/appservice/impl/DeptAppointmentHoursAppServiceImpl.java` `appointmentmanage/appservice/impl/TicketAppServiceImpl.java`
|
||||
- **Mapper**: `appointmentmanage/mapper/DoctorScheduleAppMapper.java` `appointmentmanage/mapper/SchedulePoolAppMapper.java` `appointmentmanage/mapper/DeptAppMapper.java`
|
||||
- **DTO**: `appointmentmanage/dto/TicketDto.java` `appointmentmanage/dto/SchedulePoolDto.java`
|
||||
|
||||
### `basedatamanage` (44 files)
|
||||
- **Controller**: `basedatamanage/controller/OrganizationLocationController.java` `basedatamanage/controller/BodyStructureController.java` `basedatamanage/controller/OperatingRoomController.java`
|
||||
- **AppService**: `basedatamanage/appservice/IOrganizationAppService.java` `basedatamanage/appservice/IBodyStructureAppService.java` `basedatamanage/appservice/ILocationAppService.java`
|
||||
- **ServiceImpl**: `basedatamanage/appservice/impl/PractitionerAppServiceImpl.java` `basedatamanage/appservice/impl/BodyStructureAppServiceImpl.java` `basedatamanage/appservice/impl/OrganizationAppServiceImpl.java`
|
||||
- **Mapper**: `basedatamanage/mapper/PractitionerAppAppMapper.java`
|
||||
- **DTO**: `basedatamanage/dto/SelectableOrgDto.java` `basedatamanage/dto/PractitionerOrgAndLocationDto.java` `basedatamanage/dto/OrganizationInitDto.java` `basedatamanage/dto/OperatingRoomDto.java` `basedatamanage/dto/LocationInitDto.java`
|
||||
|
||||
### `basicmanage` (5 files)
|
||||
- **Controller**: `basicmanage/controller/BedController.java` `basicmanage/controller/InvoiceController.java` `basicmanage/controller/InvoiceSegmentController.java`
|
||||
|
||||
### `basicservice` (7 files)
|
||||
- **Controller**: `basicservice/controller/HealthcareServiceController.java`
|
||||
- **Mapper**: `basicservice/mapper/HealthcareServiceBizMapper.java`
|
||||
- **DTO**: `basicservice/dto/HealthcareServiceAddOrUpdateParam.java` `basicservice/dto/HealthcareServiceDto.java` `basicservice/dto/HealthcareServiceInitDto.java`
|
||||
|
||||
### `ca` (3 files)
|
||||
- **Controller**: `ca/controller/CaSignatureController.java`
|
||||
- **AppService**: `ca/appservice/ICaSignatureAppService.java`
|
||||
- **ServiceImpl**: `ca/appservice/impl/CaSignatureAppServiceImpl.java`
|
||||
|
||||
### `cardmanagement` (17 files)
|
||||
- **Controller**: `cardmanagement/controller/CardManageController.java`
|
||||
- **AppService**: `cardmanagement/appservice/ICardManageAppService.java`
|
||||
- **ServiceImpl**: `cardmanagement/appservice/impl/CardManageAppServiceImpl.java`
|
||||
- **Mapper**: `cardmanagement/mapper/InfectiousAuditMapper.java` `cardmanagement/mapper/InfectiousCardMapper.java`
|
||||
- **DTO**: `cardmanagement/dto/InfectiousCardDto.java` `cardmanagement/dto/DoctorCardQueryDto.java` `cardmanagement/dto/DoctorCardListDto.java` `cardmanagement/dto/SingleReturnDto.java` `cardmanagement/dto/CardStatisticsDto.java`
|
||||
|
||||
### `catalogmanage` (4 files)
|
||||
- **Controller**: `catalogmanage/controller/CatalogController.java`
|
||||
- **ServiceImpl**: `catalogmanage/appservice/impl/CatalogServiceImpl.java`
|
||||
- **Mapper**: `catalogmanage/mapper/CatalogMapper.java`
|
||||
|
||||
### `charge` (4 files)
|
||||
- **Controller**: `charge/patientcardrenewal/PatientCardRenewalController.java`
|
||||
- **ServiceImpl**: `charge/patientcardrenewal/PatientCardRenewalServiceImpl.java`
|
||||
|
||||
### `chargemanage` (46 files)
|
||||
- **Controller**: `chargemanage/controller/OutpatientRegistrationController.java` `chargemanage/controller/OutpatientPricingController.java` `chargemanage/controller/InpatientChargeController.java`
|
||||
- **AppService**: `chargemanage/appservice/IInpatientChargeAppService.java` `chargemanage/appservice/IOutpatientRegistrationAppService.java` `chargemanage/appservice/IOutpatientRefundAppService.java`
|
||||
- **ServiceImpl**: `chargemanage/appservice/impl/OutpatientChargeAppServiceImpl.java` `chargemanage/appservice/impl/InpatientChargeAppServiceImpl.java` `chargemanage/appservice/impl/OutpatientRefundAppServiceImpl.java`
|
||||
- **Mapper**: `chargemanage/mapper/OutpatientRefundAppMapper.java` `chargemanage/mapper/OutpatientRegistrationAppMapper.java` `chargemanage/mapper/OutpatientChargeAppMapper.java`
|
||||
- **DTO**: `chargemanage/dto/ReprintRegistrationDto.java` `chargemanage/dto/EncounterPatientRefundDto.java` `chargemanage/dto/OutpatientPricingPriceDto.java` `chargemanage/dto/OutpatientPricingInventoryDto.java` `chargemanage/dto/RefundItemParam.java`
|
||||
|
||||
### `check` (27 files)
|
||||
- **Controller**: `check/controller/CheckMethodController.java` `check/controller/SpecimenBarcodeController.java` `check/controller/RadiologyEnhancedController.java`
|
||||
- **AppService**: `check/appservice/ILisGroupInfoAppService.java` `check/appservice/ICheckPartAppService.java` `check/appservice/ICheckMethodAppService.java`
|
||||
- **ServiceImpl**: `check/appservice/impl/CheckMethodAppServiceImpl.java` `check/appservice/impl/CheckPartAppServiceImpl.java` `check/appservice/impl/CheckPackageAppServiceImpl.java`
|
||||
- **Mapper**: `check/mapper/LisGroupInfoAppMapper.java` `check/mapper/CheckMethodAppMapper.java` `check/mapper/CheckPartAppMapper.java`
|
||||
- **DTO**: `check/dto/CheckPackageDetailDto.java` `check/dto/ExamApplyDto.java` `check/dto/ExamApplyItemDto.java` `check/dto/CheckPackageDto.java` `check/dto/CheckMethodDto.java`
|
||||
|
||||
### `clinical` (2 files)
|
||||
- **Controller**: `clinical/controller/KnowledgeBaseController.java` `clinical/controller/ClinicalPathwayController.java`
|
||||
|
||||
### `clinicalmanage` (11 files)
|
||||
- **Controller**: `clinicalmanage/controller/SurgicalScheduleController.java` `clinicalmanage/controller/SurgeryController.java`
|
||||
- **AppService**: `clinicalmanage/appservice/ISurgicalScheduleAppService.java` `clinicalmanage/appservice/ISurgeryAppService.java`
|
||||
- **ServiceImpl**: `clinicalmanage/appservice/impl/SurgicalScheduleAppServiceImpl.java` `clinicalmanage/appservice/impl/SurgeryAppServiceImpl.java`
|
||||
- **Mapper**: `clinicalmanage/mapper/SurgicalScheduleAppMapper.java` `clinicalmanage/mapper/SurgeryAppMapper.java`
|
||||
- **DTO**: `clinicalmanage/dto/SurgeryDto.java` `clinicalmanage/dto/OpScheduleDto.java` `clinicalmanage/dto/OpCreateScheduleDto.java`
|
||||
|
||||
### `common` (17 files)
|
||||
- **Controller**: `common/controller/CommonAppController.java`
|
||||
- **ServiceImpl**: `common/appservice/impl/CommonServiceImpl.java`
|
||||
- **Mapper**: `common/mapper/CommonAppMapper.java`
|
||||
- **DTO**: `common/dto/ActivityDefinitionDto.java` `common/dto/PerformInfoDto.java` `common/dto/PractitionerInfoDto.java` `common/dto/LocationInventoryDto.java` `common/dto/PerformRecordDto.java`
|
||||
|
||||
### `consultation` (19 files)
|
||||
- **Controller**: `consultation/controller/ConsultationController.java`
|
||||
- **AppService**: `consultation/appservice/IConsultationAppService.java`
|
||||
- **ServiceImpl**: `consultation/appservice/impl/ConsultationAppServiceImpl.java`
|
||||
- **Mapper**: `consultation/mapper/ConsultationInvitedMapper.java` `consultation/mapper/ConsultationConfirmationMapper.java` `consultation/mapper/ConsultationRequestMapper.java`
|
||||
- **DTO**: `consultation/dto/PhysicianNodeDto.java` `consultation/dto/InvitedObjectDto.java` `consultation/dto/ConsultationActivityDto.java` `consultation/dto/DepartmentTreeDto.java` `consultation/dto/ConsultationRequestDto.java`
|
||||
|
||||
### `controller` (2 files)
|
||||
- **Controller**: `controller/WorkflowController.java` `controller/HomeStatisticsController.java`
|
||||
|
||||
### `criticalvalue` (3 files)
|
||||
- **Controller**: `criticalvalue/controller/CriticalValueController.java`
|
||||
- **AppService**: `criticalvalue/appservice/ICriticalValueAppService.java`
|
||||
- **ServiceImpl**: `criticalvalue/appservice/impl/CriticalValueAppServiceImpl.java`
|
||||
|
||||
### `crossmodule` (3 files)
|
||||
- **Controller**: `crossmodule/controller/CrossModuleController.java` `crossmodule/controller/EnhancementController.java` `crossmodule/controller/IntegrationController.java`
|
||||
|
||||
### `datadictionary` (65 files)
|
||||
- **Controller**: `datadictionary/controller/DiagnosisTreatmentController.java` `datadictionary/controller/MedicationManageController.java` `datadictionary/controller/DiseaseManageController.java`
|
||||
- **AppService**: `datadictionary/appservice/IDeviceManageAppService.java` `datadictionary/appservice/IDiagTreatMAppService.java` `datadictionary/appservice/ItemDefinitionAppService.java`
|
||||
- **ServiceImpl**: `datadictionary/appservice/impl/DiagTreatMAppServiceImpl.java` `datadictionary/appservice/impl/SupplierManagementAppServiceImpl.java` `datadictionary/appservice/impl/ItemDefinitionAppServiceImpl.java`
|
||||
- **Mapper**: `datadictionary/mapper/MedicationManageSearchMapper.java` `datadictionary/mapper/ICDCodeMapper.java` `datadictionary/mapper/ActivityDefinitionManageMapper.java`
|
||||
- **DTO**: `datadictionary/dto/DeviceManageUpDto.java` `datadictionary/dto/ChargeItemOptionDto.java` `datadictionary/dto/SupplierDto.java` `datadictionary/dto/DiagnosisTreatmentInitDto.java` `datadictionary/dto/DiagnosisTreatmentSelParam.java`
|
||||
|
||||
### `departmentmanage` (42 files)
|
||||
- **Controller**: `departmentmanage/controller/DepartmentTransferOutOrderController.java` `departmentmanage/controller/DepartmentReturnToWarehouseOrderController.java` `departmentmanage/controller/DepartmentStocktakingOrderController.java`
|
||||
- **ServiceImpl**: `departmentmanage/appservice/impl/DepartmentReceiptApprovalServiceImpl.java` `departmentmanage/appservice/impl/DepartmentStockInOrderServiceImpl.java` `departmentmanage/appservice/impl/DepartmentCommonServiceImpl.java`
|
||||
- **Mapper**: `departmentmanage/mapper/DepartmentTransferInOrderMapper.java` `departmentmanage/mapper/DepartmentStocktakingOrderMapper.java` `departmentmanage/mapper/DepartmentTransferOutOrderMapper.java`
|
||||
- **DTO**: `departmentmanage/dto/DepartmentDeviceInfoDto.java` `departmentmanage/dto/DepartmentDetailDto.java` `departmentmanage/dto/DepartmentInitDto.java` `departmentmanage/dto/DepartmentSearchParam.java` `departmentmanage/dto/DepartmentDto.java`
|
||||
|
||||
### `doctorstation` (91 files)
|
||||
- **Controller**: `doctorstation/controller/DoctorStationDiagnosisController.java` `doctorstation/controller/DoctorStationInspectionLabApplyController.java` `doctorstation/controller/DoctorStationChineseMedicalController.java`
|
||||
- **AppService**: `doctorstation/appservice/IDoctorPhraseAppService.java` `doctorstation/appservice/IDoctorStationEmrAppService.java` `doctorstation/appservice/IDoctorStationMainAppService.java`
|
||||
- **ServiceImpl**: `doctorstation/appservice/impl/DoctorStationPtDetailsAppServiceImpl.java` `doctorstation/appservice/impl/DoctorStationElepPrescriptionServiceImpl.java` `doctorstation/appservice/impl/DoctorPhraseAppServiceImpl.java`
|
||||
- **Mapper**: `doctorstation/mapper/DoctorStationAdviceAppMapper.java` `doctorstation/mapper/DoctorStationEmrAppMapper.java` `doctorstation/mapper/DoctorStationDiagnosisAppMapper.java`
|
||||
- **DTO**: `doctorstation/dto/EncounterContractDto.java` `doctorstation/dto/AdviceInventoryDto.java` `doctorstation/dto/ActivityChildrenJsonParams.java` `doctorstation/dto/DoctorStationLabApplyItemDto.java` `doctorstation/dto/DoctorStationInitDto.java`
|
||||
|
||||
### `document` (47 files)
|
||||
- **Controller**: `document/controller/DocRecordController.java` `document/controller/DocDefinitionController.java` `document/controller/InformedConsentController.java`
|
||||
- **AppService**: `document/appservice/IDocStatisticsAppService.java` `document/appservice/IDocRecordAppService.java` `document/appservice/IDocTemplateAppService.java`
|
||||
- **ServiceImpl**: `document/appservice/impl/DocStatisticsDefinitionAppServiceImpl.java` `document/appservice/impl/DocRecordAppServiceImpl.java` `document/appservice/impl/DocStatisticsAppServiceImpl.java`
|
||||
- **Mapper**: `document/mapper/DocRecordAppMapper.java` `document/mapper/DocStatisticsDefinitionAppMapper.java` `document/mapper/DocDefinitionAppMapper.java`
|
||||
- **DTO**: `document/dto/DocStatisticsDefinitionDto.java` `document/dto/DocRecordPatientQueryParam.java` `document/dto/DocDefinitionOrganizationDto.java` `document/dto/DocRecordDto.java` `document/dto/DocTemplateDto.java`
|
||||
|
||||
### `empi` (5 files)
|
||||
- **Controller**: `empi/controller/EmpiController.java` `empi/controller/EmpiIdVerificationController.java` `empi/controller/EmpiEnhancedController.java`
|
||||
- **AppService**: `empi/appservice/IEmpiAppService.java`
|
||||
- **ServiceImpl**: `empi/appservice/impl/EmpiAppServiceImpl.java`
|
||||
|
||||
### `emr` (6 files)
|
||||
- **Controller**: `emr/controller/EmrArchiveController.java` `emr/controller/StructuredEmrController.java` `emr/controller/EmrRevisionController.java`
|
||||
- **AppService**: `emr/appservice/IStructuredEmrAppService.java`
|
||||
- **ServiceImpl**: `emr/appservice/impl/StructuredEmrAppServiceImpl.java`
|
||||
|
||||
### `epidemic` (3 files)
|
||||
- **Controller**: `epidemic/controller/EpidemicController.java`
|
||||
- **AppService**: `epidemic/appservice/IEpidemicAppService.java`
|
||||
- **ServiceImpl**: `epidemic/appservice/impl/EpidemicAppServiceImpl.java`
|
||||
|
||||
### `esbmanage` (4 files)
|
||||
- **Controller**: `esbmanage/controller/EsbReliabilityController.java` `esbmanage/controller/EsbMessageController.java` `esbmanage/controller/EsbServiceRegistryController.java`
|
||||
|
||||
### `externalintegration` (18 files)
|
||||
- **Controller**: `externalintegration/controller/FoodborneAcquisitionAppController.java`
|
||||
- **AppService**: `externalintegration/appservice/IBankPosCloudAppService.java` `externalintegration/appservice/IFoodborneAcquisitionAppService.java`
|
||||
- **ServiceImpl**: `externalintegration/appservice/impl/FoodborneAcquisitionAppServiceImpl.java` `externalintegration/appservice/impl/BankPosCloudAppServiceImpl.java`
|
||||
- **Mapper**: `externalintegration/mapper/FoodborneAcquisitionAppMapper.java`
|
||||
- **DTO**: `externalintegration/dto/BpcTransactionResponseDto.java` `externalintegration/dto/BpcPaymentScanNotifyDto.java` `externalintegration/dto/FaSimplediseaseAddNopwParam.java` `externalintegration/dto/BpcTransactionRequestDto.java` `externalintegration/dto/BpcDataElementDto.java`
|
||||
|
||||
### `infection` (4 files)
|
||||
- **Controller**: `infection/controller/InfectionEnhancedController.java` `infection/controller/InfectionController.java`
|
||||
- **AppService**: `infection/appservice/IInfectionAppService.java`
|
||||
- **ServiceImpl**: `infection/appservice/impl/InfectionAppServiceImpl.java`
|
||||
|
||||
### `inhospitalcharge` (17 files)
|
||||
- **Controller**: `inhospitalcharge/controller/AdvancePaymentManageController.java` `inhospitalcharge/controller/InHospitalRegisterController.java`
|
||||
- **AppService**: `inhospitalcharge/appservice/IInHospitalRegisterAppService.java` `inhospitalcharge/appservice/IAdvancePaymentManageAppService.java`
|
||||
- **ServiceImpl**: `inhospitalcharge/appservice/impl/AdvancePaymentManageAppServiceImpl.java` `inhospitalcharge/appservice/impl/InHospitalRegisterAppServiceImpl.java`
|
||||
- **Mapper**: `inhospitalcharge/mapper/InHospitalRegisterAppMapper.java` `inhospitalcharge/mapper/AdvancePaymentManageAppMapper.java`
|
||||
- **DTO**: `inhospitalcharge/dto/AdvancePaymentInAndOutDto.java` `inhospitalcharge/dto/PatientUpdateDto.java` `inhospitalcharge/dto/NoFilesRegisterDto.java` `inhospitalcharge/dto/InHospitalPatientInfoDto.java` `inhospitalcharge/dto/InHospitalRegisterQueryDto.java`
|
||||
|
||||
### `inhospitalnursestation` (52 files)
|
||||
- **Controller**: `inhospitalnursestation/controller/AdviceProcessController.java` `inhospitalnursestation/controller/NurseBillingController.java` `inhospitalnursestation/controller/EncounterAutoRollAppController.java`
|
||||
- **AppService**: `inhospitalnursestation/appservice/IOrgDeviceStockTakeAppService.java` `inhospitalnursestation/appservice/IAdviceProcessAppService.java` `inhospitalnursestation/appservice/INurseBillingAppService.java`
|
||||
- **ServiceImpl**: `inhospitalnursestation/appservice/impl/OrgDeviceStockTakeAppServiceImpl.java` `inhospitalnursestation/appservice/impl/ATDManageAppServiceImpl.java` `inhospitalnursestation/appservice/impl/EncounterAutoRollAppServiceImpl.java`
|
||||
- **Mapper**: `inhospitalnursestation/mapper/ATDManageAppMapper.java` `inhospitalnursestation/mapper/EncounterAutoRollAppMapper.java` `inhospitalnursestation/mapper/MedicineSummaryAppMapper.java`
|
||||
- **DTO**: `inhospitalnursestation/dto/AdmissionBedPageDto.java` `inhospitalnursestation/dto/AdviceExecuteParam.java` `inhospitalnursestation/dto/InpatientAdviceParam.java` `inhospitalnursestation/dto/DispenseFormSearchParam.java` `inhospitalnursestation/dto/AutoRollNursingDto.java`
|
||||
|
||||
### `inpatientmanage` (40 files)
|
||||
- **Controller**: `inpatientmanage/controller/NursingVitalSignsChartController.java` `inpatientmanage/controller/VitalSignsController.java` `inpatientmanage/controller/PatientHomeController.java`
|
||||
- **AppService**: `inpatientmanage/appservice/IPatientHomeAppService.java` `inpatientmanage/appservice/IDepositAppService.java` `inpatientmanage/appservice/INursingRecordAppService.java`
|
||||
- **ServiceImpl**: `inpatientmanage/appservice/impl/DepositAppServiceImpl.java` `inpatientmanage/appservice/impl/NursingRecordAppServiceImpl.java` `inpatientmanage/appservice/impl/PatientHomeAppServiceImpl.java`
|
||||
- **Mapper**: `inpatientmanage/mapper/VitalSignsAppMapper.java` `inpatientmanage/mapper/DepositMapper.java` `inpatientmanage/mapper/NursingRecordAppMapper.java`
|
||||
- **DTO**: `inpatientmanage/dto/DepositDetailDto.java` `inpatientmanage/dto/VitalSignsChartSmallDto.java` `inpatientmanage/dto/VitalSignsSaveDto.java` `inpatientmanage/dto/PatientHomeSearchParam.java` `inpatientmanage/dto/PatientHomeEmptyBedDto.java`
|
||||
|
||||
### `inventorymanage` (107 files)
|
||||
- **Controller**: `inventorymanage/controller/PurchaseReturnController.java` `inventorymanage/controller/InventorySettlementController.java` `inventorymanage/controller/ReturnIssueController.java`
|
||||
- **AppService**: `inventorymanage/appservice/IProductStocktakingAppService.java` `inventorymanage/appservice/IInventoryDetailsAppService.java` `inventorymanage/appservice/IReturnIssueAppService.java`
|
||||
- **ServiceImpl**: `inventorymanage/appservice/impl/InventoryDetailsAppServiceImpl.java` `inventorymanage/appservice/impl/ProductTransferAppServiceImpl.java` `inventorymanage/appservice/impl/ReceiptApprovalAppServiceImpl.java`
|
||||
- **Mapper**: `inventorymanage/mapper/ProductDetailAppMapper.java` `inventorymanage/mapper/RequisitionIssueMapper.java` `inventorymanage/mapper/PurchaseReturnMapper.java`
|
||||
- **DTO**: `inventorymanage/dto/ProductTransferPageDto.java` `inventorymanage/dto/PurchaseInventoryDto.java` `inventorymanage/dto/ReceiptDetailDto.java` `inventorymanage/dto/RequisitionOutDetailDto.java` `inventorymanage/dto/InventoryReceiptDetailDto.java`
|
||||
|
||||
### `jlau` (5 files)
|
||||
- **Controller**: `jlau/controller/ReviewPrescriptionRecordsController.java`
|
||||
- **AppService**: `jlau/appservice/IReviewPrescriptionRecordsAppService.java`
|
||||
- **ServiceImpl**: `jlau/appservice/impl/ReviewPrescriptionRecordsAppServiceImpl.java`
|
||||
- **Mapper**: `jlau/mapper/ReviewPrescriptionRecordsAppMapper.java`
|
||||
- **DTO**: `jlau/dto/ReviewPrescriptionRecordsDto.java`
|
||||
|
||||
### `lab` (7 files)
|
||||
- **Controller**: `lab/controller/LabActivityDefinitionController.java` `lab/controller/LabHistoryController.java` `lab/controller/LabEnhancedController.java`
|
||||
- **AppService**: `lab/appservice/ILabActivityDefinitionAppService.java`
|
||||
- **ServiceImpl**: `lab/appservice/impl/LabActivityDefinitionAppServiceImpl.java`
|
||||
|
||||
### `materialmanage` (46 files)
|
||||
- **Controller**: `materialmanage/controller/MaterialReturnOrderController.java` `materialmanage/controller/MaterialTransferInOrderController.java` `materialmanage/controller/MaterialTransferOutOrderController.java`
|
||||
- **ServiceImpl**: `materialmanage/appservice/impl/MaterialPurchaseOrderServiceImpl.java` `materialmanage/appservice/impl/MaterialTransferOutOrderServiceImpl.java` `materialmanage/appservice/impl/MaterialReturnToWarehouseOrderServiceImpl.java`
|
||||
- **Mapper**: `materialmanage/mapper/MaterialCommonMapper.java` `materialmanage/mapper/MaterialProfitLossOrderMapper.java` `materialmanage/mapper/MaterialTransferOutOrderMapper.java`
|
||||
- **DTO**: `materialmanage/dto/MaterialInitDto.java` `materialmanage/dto/MaterialSearchParam.java` `materialmanage/dto/MaterialDto.java` `materialmanage/dto/MaterialDetailDto.java` `materialmanage/dto/MaterialDeviceInfoDto.java`
|
||||
|
||||
### `mrhomepage` (6 files)
|
||||
- **Controller**: `mrhomepage/controller/DrgAnalysisController.java` `mrhomepage/controller/MrManagementController.java` `mrhomepage/controller/MrHomepageController.java`
|
||||
- **AppService**: `mrhomepage/appservice/IMrHomepageAppService.java`
|
||||
- **ServiceImpl**: `mrhomepage/appservice/impl/MrHomepageAppServiceImpl.java`
|
||||
|
||||
### `nenu` (22 files)
|
||||
- **Controller**: `nenu/controller/GfRatioApplicationRecordController.java` `nenu/controller/GfStudentListController.java` `nenu/controller/GfRatioManageController.java`
|
||||
- **AppService**: `nenu/appservice/IGfRatioManageAppService.java` `nenu/appservice/IGfRatioApplicationRecordAppService.java` `nenu/appservice/IGfStudentListAppService.java`
|
||||
- **ServiceImpl**: `nenu/appservice/impl/GfRatioApplicationRecordAppServiceImpl.java` `nenu/appservice/impl/GfRatioManageAppServiceImpl.java` `nenu/appservice/impl/GfStudentListAppServiceImpl.java`
|
||||
- **Mapper**: `nenu/mapper/GfStudentListAppMapper.java` `nenu/mapper/GfRatioManageAppMapper.java` `nenu/mapper/GfRatioApplicationRecordAppMapper.java`
|
||||
- **DTO**: `nenu/dto/GfIndividualRatioDto.java` `nenu/dto/GfRatioApplicationRecordDto.java` `nenu/dto/GfStudentListImportDto.java` `nenu/dto/GfRatioApplicationProcessDto.java` `nenu/dto/GfStudentPeisDto.java`
|
||||
|
||||
### `nursing` (8 files)
|
||||
- **Controller**: `nursing/controller/NursingExecutionController.java` `nursing/controller/NursingAssessmentEnhancedController.java` `nursing/controller/NursingEnhancedController.java`
|
||||
- **AppService**: `nursing/appservice/INursingAppService.java`
|
||||
- **ServiceImpl**: `nursing/appservice/impl/NursingAppServiceImpl.java`
|
||||
|
||||
### `orderclosedloop` (3 files)
|
||||
- **Controller**: `orderclosedloop/controller/OrderClosedLoopController.java`
|
||||
- **AppService**: `orderclosedloop/appservice/IOrderClosedLoopAppService.java`
|
||||
- **ServiceImpl**: `orderclosedloop/appservice/impl/OrderClosedLoopAppServiceImpl.java`
|
||||
|
||||
### `outpatientmanage` (22 files)
|
||||
- **Controller**: `outpatientmanage/controller/OutpatientTreatmentController.java` `outpatientmanage/controller/OutpatientSkinTestAppController.java` `outpatientmanage/controller/OutpatientInfusionController.java`
|
||||
- **AppService**: `outpatientmanage/appservice/IOutpatientTreatmentAppService.java` `outpatientmanage/appservice/IOutpatientInfusionAppService.java` `outpatientmanage/appservice/IOutpatientSkinTestAppService.java`
|
||||
- **ServiceImpl**: `outpatientmanage/appservice/impl/OutpatientTreatmentAppServiceImpl.java` `outpatientmanage/appservice/impl/OutpatientSkinTestAppServiceImpl.java` `outpatientmanage/appservice/impl/OutpatientInfusionAppServiceImpl.java`
|
||||
- **Mapper**: `outpatientmanage/mapper/OutpatientTreatmentAppMapper.java` `outpatientmanage/mapper/OutpatientInfusionAppMapper.java` `outpatientmanage/mapper/OutpatientSkinTestAppMapper.java`
|
||||
- **DTO**: `outpatientmanage/dto/SkinTestMedLotNumberDto.java` `outpatientmanage/dto/OutpatientInfusionRecordDto.java` `outpatientmanage/dto/SkinTestSaveDto.java` `outpatientmanage/dto/OutpatientTreatmentInfoDto.java` `outpatientmanage/dto/OutpatientStationInitDto.java`
|
||||
|
||||
### `patientmanage` (13 files)
|
||||
- **Controller**: `patientmanage/controller/PatientInformationController.java` `patientmanage/controller/OutpatientRecordController.java`
|
||||
- **ServiceImpl**: `patientmanage/appservice/impl/OutpatientRecordServiceImpl.java` `patientmanage/appservice/impl/PatientInformationServiceImpl.java`
|
||||
- **Mapper**: `patientmanage/mapper/PatientManageMapper.java`
|
||||
- **DTO**: `patientmanage/dto/PatientInfoInitDto.java` `patientmanage/dto/PatientIdInfoDto.java` `patientmanage/dto/OutpatientRecordSearchParam.java` `patientmanage/dto/PatientBaseInfoDto.java` `patientmanage/dto/OutpatientRecordDto.java`
|
||||
|
||||
### `paymentmanage` (57 files)
|
||||
- **Controller**: `paymentmanage/controller/EleInvoiceController.java` `paymentmanage/controller/ChargeBillController.java` `paymentmanage/controller/PaymentContractController.java`
|
||||
- **ServiceImpl**: `paymentmanage/appservice/impl/PaymentRecServiceImpl.java` `paymentmanage/appservice/impl/IChargeBillServiceImpl.java` `paymentmanage/appservice/impl/EleInvoiceServiceImpl.java`
|
||||
- **Mapper**: `paymentmanage/mapper/EleInvoiceMapper.java` `paymentmanage/mapper/ThreePartPayMapper.java` `paymentmanage/mapper/ChangePriceMapper.java`
|
||||
- **DTO**: `paymentmanage/dto/NenuBpcPayDto.java` `paymentmanage/dto/EleInvoiceResultDto.java` `paymentmanage/dto/ChargeSummaryDto.java` `paymentmanage/dto/EleInvoicePaymentInfoDto.java` `paymentmanage/dto/Clinic2207OrderResultInfoDto.java`
|
||||
|
||||
### `personalization` (22 files)
|
||||
- **Controller**: `personalization/controller/ActivityDeviceController.java` `personalization/controller/OrdersGroupPackageController.java` `personalization/controller/OrderGroupController.java`
|
||||
- **AppService**: `personalization/appservice/IOrderGroupAppService.java` `personalization/appservice/IOrdersGroupPackageAppService.java` `personalization/appservice/IActivityDeviceAppService.java`
|
||||
- **ServiceImpl**: `personalization/appservice/impl/OrdersGroupPackageAppServiceImpl.java` `personalization/appservice/impl/ActivityDeviceAppServiceImpl.java` `personalization/appservice/impl/IOrderGroupAppServiceImpl.java`
|
||||
- **Mapper**: `personalization/mapper/OrdersGroupPackageAppMapper.java` `personalization/mapper/OrderGroupAppMapper.java` `personalization/mapper/ActivityDeviceAppMapper.java`
|
||||
- **DTO**: `personalization/dto/OrdersGroupPackageDetailSaveDto.java` `personalization/dto/OrderGroupDto.java` `personalization/dto/OrdersGroupPackageDto.java` `personalization/dto/OrderGroupInitDto.java` `personalization/dto/OrdersGroupPackageDetailQueryDto.java`
|
||||
|
||||
### `pharmacyDispensarymanage` (42 files)
|
||||
- **Controller**: `pharmacyDispensarymanage/controller/PharmacyDispensaryTransferOutOrderController.java` `pharmacyDispensarymanage/controller/PharmacyDispensaryDispensingOrderController.java` `pharmacyDispensarymanage/controller/PharmacyDispensaryStocktakingOrderController.java`
|
||||
- **ServiceImpl**: `pharmacyDispensarymanage/appservice/impl/PharmacyDispensaryStocktakingOrderServiceImpl.java` `pharmacyDispensarymanage/appservice/impl/PharmacyDispensaryTransferInOrderServiceImpl.java` `pharmacyDispensarymanage/appservice/impl/PharmacyDispensaryStockInOrderServiceImpl.java`
|
||||
- **Mapper**: `pharmacyDispensarymanage/mapper/PharmacyDispensaryReturnToWarehouseOrderMapper.java` `pharmacyDispensarymanage/mapper/PharmacyDispensaryTransferOutOrderMapper.java` `pharmacyDispensarymanage/mapper/PharmacyDispensaryRequisitionOrderMapper.java`
|
||||
- **DTO**: `pharmacyDispensarymanage/dto/PharmacyDispensaryDto.java` `pharmacyDispensarymanage/dto/PharmacyDispensaryDetailDto.java` `pharmacyDispensarymanage/dto/PharmacyDispensarySearchParam.java` `pharmacyDispensarymanage/dto/PharmacyDispensaryMedicationInfoDto.java` `pharmacyDispensarymanage/dto/PharmacyDispensaryInitDto.java`
|
||||
|
||||
### `pharmacyWarehousemanage` (42 files)
|
||||
- **Controller**: `pharmacyWarehousemanage/controller/PharmacyWarehouseProfitLossOrderController.java` `pharmacyWarehousemanage/controller/PharmacyWarehouseReturnToWarehouseOrderController.java` `pharmacyWarehousemanage/controller/PharmacyWarehouseStockOutOrderController.java`
|
||||
- **ServiceImpl**: `pharmacyWarehousemanage/appservice/impl/PharmacyWarehousePurchaseOrderServiceImpl.java` `pharmacyWarehousemanage/appservice/impl/PharmacyWarehouseDocumentManagementServiceImpl.java` `pharmacyWarehousemanage/appservice/impl/PharmacyWarehouseProfitLossOrderServiceImpl.java`
|
||||
- **Mapper**: `pharmacyWarehousemanage/mapper/PharmacyWarehousePurchaseOrderMapper.java` `pharmacyWarehousemanage/mapper/PharmacyWarehouseDocumentManagementMapper.java` `pharmacyWarehousemanage/mapper/PharmacyWarehouseStockInOrderMapper.java`
|
||||
- **DTO**: `pharmacyWarehousemanage/dto/PharmacyWarehouseDto.java` `pharmacyWarehousemanage/dto/PharmacyWarehouseDetailDto.java` `pharmacyWarehousemanage/dto/PharmacyWarehouseMedicationInfoDto.java` `pharmacyWarehousemanage/dto/PharmacyWarehouseInitDto.java` `pharmacyWarehousemanage/dto/PharmacyWarehouseSearchParam.java`
|
||||
|
||||
### `pharmacymanage` (53 files)
|
||||
- **Controller**: `pharmacymanage/controller/InHospitalReturnMedicineController.java` `pharmacymanage/controller/PharmacyStockAlertController.java` `pharmacymanage/controller/MedicationDetailsController.java`
|
||||
- **AppService**: `pharmacymanage/appservice/ISummaryDispenseMedicineAppService.java` `pharmacymanage/appservice/IPendingMedicationDetailsAppService.java` `pharmacymanage/appservice/IInHospitalReturnMedicineAppService.java`
|
||||
- **ServiceImpl**: `pharmacymanage/appservice/impl/ReturnMedicineAppServiceImpl.java` `pharmacymanage/appservice/impl/MedicationDetailsAppServiceImpl.java` `pharmacymanage/appservice/impl/WesternMedicineDispenseAppServiceImpl.java`
|
||||
- **Mapper**: `pharmacymanage/mapper/PendingMedicationDetailsMapper.java` `pharmacymanage/mapper/MedicalDeviceDispenseMapper.java` `pharmacymanage/mapper/SummaryDispenseMedicineMapper.java`
|
||||
- **DTO**: `pharmacymanage/dto/MedDetailsInitDto.java` `pharmacymanage/dto/EncounterInfoSearchParam.java` `pharmacymanage/dto/ItemDispenseOrderDto.java` `pharmacymanage/dto/MedicineSummaryDto.java` `pharmacymanage/dto/MedicineSummarySearchParam.java`
|
||||
|
||||
### `quality` (5 files)
|
||||
- **Controller**: `quality/controller/BusinessAnalyticsController.java` `quality/controller/QualityEnhancedController.java` `quality/controller/EmrQualityController.java`
|
||||
- **AppService**: `quality/appservice/IEmrQualityAppService.java`
|
||||
- **ServiceImpl**: `quality/appservice/impl/EmrQualityAppServiceImpl.java`
|
||||
|
||||
### `rationaldrug` (3 files)
|
||||
- **Controller**: `rationaldrug/controller/RationalDrugController.java`
|
||||
- **AppService**: `rationaldrug/appservice/IRationalDrugAppService.java`
|
||||
- **ServiceImpl**: `rationaldrug/appservice/impl/RationalDrugAppServiceImpl.java`
|
||||
|
||||
### `regdoctorstation` (38 files)
|
||||
- **Controller**: `regdoctorstation/controller/NurseManageController.java` `regdoctorstation/controller/AdviceManageController.java` `regdoctorstation/controller/SpecialAdviceController.java`
|
||||
- **AppService**: `regdoctorstation/appservice/IAdviceManageAppService.java` `regdoctorstation/appservice/IRequestFormManageAppService.java` `regdoctorstation/appservice/ISpecialAdviceAppService.java`
|
||||
- **ServiceImpl**: `regdoctorstation/appservice/impl/SpecialAdviceAppServiceImpl.java` `regdoctorstation/appservice/impl/RequestFormManageAppServiceImpl.java` `regdoctorstation/appservice/impl/NurseManageServiceImpl.java`
|
||||
- **Mapper**: `regdoctorstation/mapper/RequestFormManageAppMapper.java` `regdoctorstation/mapper/AdviceManageAppMapper.java` `regdoctorstation/mapper/SpecialAdviceAppMapper.java`
|
||||
- **DTO**: `regdoctorstation/dto/RegPatientMainInfoDto.java` `regdoctorstation/dto/NursingOrdersDetailDto.java` `regdoctorstation/dto/LeaveHospitalParam.java` `regdoctorstation/dto/NursingOrdersSaveDto.java` `regdoctorstation/dto/NursingOrdersEncounterDto.java`
|
||||
|
||||
### `reportManagement` (11 files)
|
||||
- **Controller**: `reportManagement/controller/reportManagementController.java`
|
||||
- **AppService**: `reportManagement/appservice/IInfectiousCardAppService.java`
|
||||
- **ServiceImpl**: `reportManagement/appservice/impl/InfectiousCardAppServiceImpl.java`
|
||||
- **Mapper**: `reportManagement/mapper/ReportManageCardMapper.java`
|
||||
- **DTO**: `reportManagement/dto/InfectiousCardDto.java` `reportManagement/dto/InfectiousCardParam.java`
|
||||
|
||||
### `reportmanage` (164 files)
|
||||
- **Controller**: `reportmanage/controller/AmbAdviceStatisticsAppController.java` `reportmanage/controller/MonthlySettlementController.java` `reportmanage/controller/PurchaseReturnReportController.java`
|
||||
- **AppService**: `reportmanage/appservice/PurchaseReturnReportAppService.java` `reportmanage/appservice/IDrugDosageSettlementAppService.java` `reportmanage/appservice/IDepartmentRevenueStatisticsAppService.java`
|
||||
- **ServiceImpl**: `reportmanage/appservice/impl/InboundReportAppServiceImpl.java` `reportmanage/appservice/impl/MedicationInboundReportAppServiceImpl.java` `reportmanage/appservice/impl/ReportStatisticsAppServiceImpl.java`
|
||||
- **Mapper**: `reportmanage/mapper/PrintReportMapper.java` `reportmanage/mapper/ReportStatisticsMapper.java` `reportmanage/mapper/LossReportMapper.java`
|
||||
- **DTO**: `reportmanage/dto/ReportDiseaseDetailsDto.java` `reportmanage/dto/InboundReportSearchParam.java` `reportmanage/dto/InpatientMedicalRecordHomePageCollectionDto.java` `reportmanage/dto/ZyCostDetailParam.java` `reportmanage/dto/BottleLabelDto.java`
|
||||
|
||||
### `review` (3 files)
|
||||
- **Controller**: `review/controller/ReviewController.java`
|
||||
- **AppService**: `review/appservice/IReviewAppService.java`
|
||||
- **ServiceImpl**: `review/appservice/impl/ReviewAppServiceImpl.java`
|
||||
|
||||
### `service` (2 files)
|
||||
- **ServiceImpl**: `service/impl/HomeStatisticsServiceImpl.java`
|
||||
|
||||
### `system` (5 files)
|
||||
- **Controller**: `system/controller/ApiAuthController.java` `system/controller/DashboardController.java` `system/controller/SysAuditLogController.java`
|
||||
|
||||
### `tcm` (3 files)
|
||||
- **Controller**: `tcm/controller/TcmController.java`
|
||||
- **AppService**: `tcm/appservice/ITcmAppService.java`
|
||||
- **ServiceImpl**: `tcm/appservice/impl/TcmAppServiceImpl.java`
|
||||
|
||||
### `tencentJH` (13 files)
|
||||
- **Controller**: `tencentJH/controller/TencentController.java`
|
||||
- **AppService**: `tencentJH/appservice/ITencentAppService.java`
|
||||
- **ServiceImpl**: `tencentJH/appservice/impl/TencentAppServiceImpl.java`
|
||||
- **Mapper**: `tencentJH/mapper/TencentAppMapper.java`
|
||||
- **DTO**: `tencentJH/dto/PatientInfoTencentDto.java` `tencentJH/dto/CurrentDayEncounterTencentDto.java`
|
||||
|
||||
### `triageandqueuemanage` (13 files)
|
||||
- **Controller**: `triageandqueuemanage/controller/CallNumberVoiceConfigController.java` `triageandqueuemanage/controller/TriageQueueController.java`
|
||||
- **AppService**: `triageandqueuemanage/appservice/CallNumberVoiceConfigAppService.java` `triageandqueuemanage/appservice/TriageQueueAppService.java`
|
||||
- **ServiceImpl**: `triageandqueuemanage/appservice/impl/CallNumberVoiceConfigAppServiceImpl.java` `triageandqueuemanage/appservice/impl/TriageQueueAppServiceImpl.java`
|
||||
- **Mapper**: `triageandqueuemanage/mapper/CallNumberVoiceConfigAppMapper.java`
|
||||
|
||||
### `ybmanage` (55 files)
|
||||
- **Controller**: `ybmanage/controller/YbInpatientController.java` `ybmanage/controller/YbElepController.java` `ybmanage/controller/YbController.java`
|
||||
- **ServiceImpl**: `ybmanage/service/impl/YbEleHttpServiceImpl.java` `ybmanage/service/impl/YbServiceImpl.java` `ybmanage/service/impl/YbElepBaseServiceImpl.java`
|
||||
- **Mapper**: `ybmanage/mapper/YbElepMapper.java` `ybmanage/mapper/YbMapper.java`
|
||||
- **DTO**: `ybmanage/dto/FinancialHand3203AWebParam.java` `ybmanage/dto/FinancialHand3201WebParam.java` `ybmanage/dto/Financial13203WebParam.java` `ybmanage/dto/VeriPrescriptionInfoDto.java` `ybmanage/dto/YbInHospitalRegisterQueryDto.java`
|
||||
|
||||
## 前端关键文件
|
||||
|
||||
| 目录 | 说明 |
|
||||
|---|---|
|
||||
| `src/utils/request.js` | Axios 请求/响应拦截器 |
|
||||
| `src/api/` | API 接口定义 |
|
||||
| `src/components/` | 公共组件 |
|
||||
| `src/views/doctorstation/` | 门诊医生站 |
|
||||
| `src/views/inpatientDoctor/` | 住院医生站 |
|
||||
| `src/views/inpatientNurse/` | 住院护士站 |
|
||||
| `src/views/charge/` | 收费工作站 |
|
||||
| `src/views/datadictionary/` | 数据字典 |
|
||||
| `src/views/system/` | 系统管理 |
|
||||
|
||||
## 公共/通用文件
|
||||
|
||||
- `com.core.common.core.domain.R` — 统一响应封装
|
||||
- `com.core.common.core.domain.entity.SysDictData` — 字典数据实体
|
||||
- `com.core.common.utils.SecurityUtils` — 安全工具(获取当前用户)
|
||||
- `com.core.common.enums.*` — 枚举定义
|
||||
- `com.healthlink.his.common.constant.CommonConstants` — 公共常量
|
||||
- `com.healthlink.his.common.utils.HisQueryUtils` — 查询工具
|
||||
- `com.healthlink.his.common.utils.HisPageUtils` — 分页工具
|
||||
- `com.healthlink.his.web.doctorstation.utils.AdviceUtils` — 医嘱工具类
|
||||
|
||||
|
||||
=== 已生成 421 行索引 ===
|
||||
25
MD/bugs/BUG_698_ANALYSIS.md
Normal file
25
MD/bugs/BUG_698_ANALYSIS.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Bug #698 诸葛亮分析报告
|
||||
|
||||
> **文档类型**: Bug分析
|
||||
> **分析时间**: 2026-06-11 16:51:39
|
||||
> **分析模型**: mimo-v2.5 (LLM深度分析)
|
||||
|
||||
---
|
||||
|
||||
## 基本信息
|
||||
- **Bug #**: 698
|
||||
- **标题**: [收费工作站-住院登记-已登记入院] 检索维度单一,且关键归档信息缺失(需增设检索条件与补充列表字段展示)
|
||||
- **模块**: 住院登记管理
|
||||
- **提出人**: 陈显精
|
||||
|
||||
---
|
||||
|
||||
(LLM 失败,关键词分析)
|
||||
Bug: [收费工作站-住院登记-已登记入院] 检索维度单一,且关键归档信息缺失(需增设检索条件与补充列表字段展示)
|
||||
模块: 住院登记管理
|
||||
|
||||
---
|
||||
|
||||
## 路由决策
|
||||
- **修复 Agent**: zhaoyun
|
||||
- **原因**: 关键词: 前端
|
||||
84
MD/bugs/BUG_741_ANALYSIS.md
Normal file
84
MD/bugs/BUG_741_ANALYSIS.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# Bug #741 诸葛亮分析报告
|
||||
|
||||
> **文档类型**: Bug分析
|
||||
> **分析时间**: 2026-06-12 11:46:17
|
||||
> **分析模型**: mimo-v2.5 (LLM深度分析)
|
||||
|
||||
---
|
||||
|
||||
## 基本信息
|
||||
- **Bug #**: 741
|
||||
- **标题**: 【住院医生工作站】打开门诊医生工作站会有代码列表报错
|
||||
- **模块**: 住院医生工作站
|
||||
- **提出人**: 王栩坤
|
||||
|
||||
---
|
||||
|
||||
### 一、Bug 理解
|
||||
|
||||
用户登录 doctor1 账号进入**住院医生工作站**页面时,页面加载过程中某个 API 请求返回了 500 错误,错误信息为 `class java.util.ArrayList cannot be cast to class com.fasterxml.jackson.databind.JsonNode`。这个 Java ClassCastException 被前端 `request.js` 拦截器捕获并弹出错误提示,导致页面功能异常。期望是页面能正常加载,患者列表和各 Tab 页正常工作。
|
||||
|
||||
### 二、根因分析
|
||||
|
||||
**直接原因**:后端某个 API 接口在处理请求或序列化响应时,抛出了 `ClassCastException: ArrayList cannot be cast to JsonNode`。异常被 `GlobalExceptionHandler` 捕获后返回 `{code:500, msg:"class java.util.ArrayList cannot be cast to class com.fasterxml.jackson.databind.JsonNode"}`。
|
||||
|
||||
**根因定位**:commit `68cfa4882` 修改了 `ApplicationConfig`,将 `Jackson2ObjectMapperBuilderCustomizer` 替换为直接创建 `new ObjectMapper()` 的 `@Bean`。
|
||||
|
||||
```java
|
||||
// 旧代码 — 定制 Spring Boot 自动配置的 ObjectMapper
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
|
||||
return builder -> { ... };
|
||||
}
|
||||
|
||||
// 新代码 — 直接覆盖 Spring Boot 自动配置的 ObjectMapper
|
||||
@Bean
|
||||
public ObjectMapper objectMapper() {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
**问题机制**:
|
||||
1. 定义 `@Bean ObjectMapper` 会**替换** Spring Boot 自动配置的 `ObjectMapper`,丢失大量自动配置(模块注册、类型解析器、序列化注解处理等)
|
||||
2. Spring Boot 4.x 的 `MappingJackson2HttpMessageConverter` 使用此 Bean 做响应序列化
|
||||
3. 当 `DictAspect`(拦截所有 `@GetMapping`/`@PostMapping`)处理 `R<IPage<RegPatientMainInfoDto>>` 响应时,`IPage` 的泛型信息在新 `ObjectMapper` 下无法正确解析
|
||||
4. Jackson 内部在序列化过程中尝试将 `ArrayList`(`IPage` 内部的 records 列表)强转为 `JsonNode`,导致 `ClassCastException`
|
||||
|
||||
**涉及文件**:
|
||||
- `core-framework/.../ApplicationConfig.java` — **根因所在**,ObjectMapper Bean 配置不当
|
||||
- `healthlink-his-common/.../DictAspect.java` — 拦截所有 Controller 方法,触发序列化链路
|
||||
- `regdoctorstation/.../AdviceManageController.java` — `/reg-patient-zk` 端点
|
||||
- `regdoctorstation/.../AdviceManageAppServiceImpl.java` — `getRegPatientMainInfo()` 返回 `IPage`
|
||||
- `utils/request.js` — 前端拦截器,line 186 抛出 Promise reject
|
||||
|
||||
### 三、修复方案
|
||||
|
||||
**修改文件**:`core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java`
|
||||
|
||||
**修复方式**:将 `@Bean ObjectMapper` 回退为 `Jackson2ObjectMapperBuilderCustomizer`,这样 Spring Boot 自动配置的 ObjectMapper 保持不变,只在其基础上追加自定义配置:
|
||||
|
||||
```java
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
|
||||
return builder -> {
|
||||
builder.timeZone(TimeZone.getDefault());
|
||||
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
javaTimeModule.addDeserializer(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER);
|
||||
javaTimeModule.addSerializer(LocalDateTime.class,
|
||||
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
builder.modules(javaTimeModule);
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**验证步骤**:
|
||||
1. `mvn clean compile -DskipTests` — 编译通过
|
||||
2. 启动应用 → 以 doctor1 登录 → 进入住院医生工作站 → 确认无报错
|
||||
3. 验证患者列表正常加载、诊断/医嘱 Tab 页正常切换
|
||||
|
||||
### 四、路由决策
|
||||
|
||||
- **修复 Agent**: guanyu(后端开发)
|
||||
- **原因**: 修复点在 `ApplicationConfig.java` 的 ObjectMapper Bean 配置,属于后端 Spring 配置问题,需要回退 Jackson 序列化配置并验证编译通过。
|
||||
43
MD/bugs/BUG_诊疗目录_SYSDESDICT_ANALYSIS.md
Normal file
43
MD/bugs/BUG_诊疗目录_SYSDESDICT_ANALYSIS.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# 诊疗目录 SysDictData 反序列化错误 诸葛亮分析报告
|
||||
|
||||
> **文档类型**: Bug分析
|
||||
> **分析时间**: 2026-06-11
|
||||
> **分析模型**: mimo-v2.5 (LLM深度分析)
|
||||
|
||||
---
|
||||
|
||||
## 基本信息
|
||||
- **标题**: 诊疗目录 /system/catalog/diagnosistreatment 进入报错
|
||||
- **错误**: Cannot deserialize value of type SysDictData from Array value
|
||||
- **模块**: 诊疗目录管理
|
||||
|
||||
---
|
||||
|
||||
## 根因分析
|
||||
|
||||
**根本原因**: commit `68cfa4882` 将 Jackson 配置从 `Jackson2ObjectMapperBuilderCustomizer` 改为直接定义 `ObjectMapper` bean。
|
||||
|
||||
直接定义 `ObjectMapper` bean 会导致 Spring Boot 的 Jackson 自动配置完全失效:
|
||||
1. Spring Boot 默认的 Jackson 模块(如 `jackson-datatype-jdk8`、`jackson-datatype-jsr310`)不会自动注册
|
||||
2. 默认的序列化/反序列化特性设置丢失
|
||||
3. `ObjectMapper` 的默认可见性设置可能不同
|
||||
|
||||
当 `DictAspect` 处理 `@Dict` 注解的 DTO 时,Jackson 在序列化/反序列化过程中遇到 `SysDictData` 类型,由于缺少正确的模块配置,无法正确处理嵌套的数组/对象结构。
|
||||
|
||||
## 修复方案
|
||||
|
||||
将 `ApplicationConfig.java` 中的 `ObjectMapper` bean 改回 `Jackson2ObjectMapperBuilderCustomizer`,让 Spring Boot 自动配置保持生效。
|
||||
|
||||
### 修改文件
|
||||
- `core-framework/src/main/java/com/core/framework/config/ApplicationConfig.java`
|
||||
|
||||
### 修改内容
|
||||
- `public ObjectMapper objectMapper()` → `public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()`
|
||||
- 移除手动创建的 `ObjectMapper` 实例
|
||||
- 使用 builder 模式配置,保留 Spring Boot 默认设置
|
||||
|
||||
---
|
||||
|
||||
## 路由决策
|
||||
- **修复 Agent**: guanyu (后端)
|
||||
- **原因**: Jackson 配置问题,纯后端修改
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
# 前端发布前检查清单
|
||||
|
||||
> **文档类型**: 技术规范
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"test_time": "2026-06-08T09:11:33.934379",
|
||||
"test_time": "2026-06-08T11:20:49.248056",
|
||||
"environment": "http://localhost:18082/healthlink-his",
|
||||
"total": 125,
|
||||
"passed": 125,
|
||||
@@ -167,7 +167,7 @@
|
||||
"id": "OP-PHARM",
|
||||
"name": "待发药列表",
|
||||
"ok": true,
|
||||
"detail": "待发药=534"
|
||||
"detail": "待发药=532"
|
||||
},
|
||||
{
|
||||
"id": "OP-WEST",
|
||||
@@ -377,13 +377,13 @@
|
||||
"id": "INS-3D",
|
||||
"name": "3D重建任务",
|
||||
"ok": true,
|
||||
"detail": "任务=0"
|
||||
"detail": "任务=14"
|
||||
},
|
||||
{
|
||||
"id": "INS-3D-RPT",
|
||||
"name": "3D重建报告",
|
||||
"ok": true,
|
||||
"detail": "报告=0"
|
||||
"detail": "报告=11"
|
||||
},
|
||||
{
|
||||
"id": "INS-RAD-RPT",
|
||||
@@ -695,7 +695,7 @@
|
||||
"id": "MR-05-PHARM",
|
||||
"name": "药师→待发药",
|
||||
"ok": true,
|
||||
"detail": "待发药=534"
|
||||
"detail": "待发药=532"
|
||||
},
|
||||
{
|
||||
"id": "MR-06-CHARGE",
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
# ============================================================
|
||||
# OpenHIS 前端部署脚本 (Windows PowerShell)
|
||||
# 用法: .\deploy-frontend.ps1 [-Env prod|test|staging|dev]
|
||||
# ============================================================
|
||||
param(
|
||||
[ValidateSet("prod","test","staging","dev")]
|
||||
[string]$Env = "prod"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$ProjectDir = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
||||
$UiDir = "$ProjectDir\openhis-ui-vue3"
|
||||
$DistDir = "$UiDir\dist"
|
||||
|
||||
Write-Host "==========================================" -ForegroundColor Cyan
|
||||
Write-Host " OpenHIS 前端部署" -ForegroundColor Cyan
|
||||
Write-Host " 环境: $Env" -ForegroundColor Cyan
|
||||
Write-Host " 目录: $UiDir" -ForegroundColor Cyan
|
||||
Write-Host "==========================================" -ForegroundColor Cyan
|
||||
|
||||
# ---------- 1. 环境检查 ----------
|
||||
Write-Host "`n[1/5] 环境检查..." -ForegroundColor Yellow
|
||||
|
||||
try { $nodeVer = node -v } catch { Write-Host "错误: 未找到 node" -ForegroundColor Red; exit 1 }
|
||||
try { $npmVer = npm -v } catch { Write-Host "错误: 未找到 npm" -ForegroundColor Red; exit 1 }
|
||||
|
||||
$nodeMajor = [int]($nodeVer -replace 'v','' -split '\.')[0]
|
||||
if ($nodeMajor -lt 18) {
|
||||
Write-Host "错误: Node.js >= 18,当前 $nodeVer" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Write-Host " Node.js: $nodeVer ✓"
|
||||
Write-Host " npm: $npmVer ✓"
|
||||
|
||||
# ---------- 2. 安装依赖 ----------
|
||||
Write-Host "`n[2/5] 安装依赖..." -ForegroundColor Yellow
|
||||
Set-Location $UiDir
|
||||
npm install --legacy-peer-deps
|
||||
Write-Host " 依赖安装完成 ✓" -ForegroundColor Green
|
||||
|
||||
# ---------- 3. 构建 ----------
|
||||
Write-Host "`n[3/5] 构建 ($Env)..." -ForegroundColor Yellow
|
||||
npm run "build:$Env"
|
||||
Write-Host " 构建完成 ✓" -ForegroundColor Green
|
||||
|
||||
# ---------- 4. 产物信息 ----------
|
||||
Write-Host "`n[4/5] 构建产物:" -ForegroundColor Yellow
|
||||
$totalSize = (Get-ChildItem $DistDir -Recurse -File | Measure-Object -Property Length -Sum).Sum
|
||||
$fileCount = (Get-ChildItem $DistDir -Recurse -File).Count
|
||||
Write-Host " 路径: $DistDir"
|
||||
Write-Host " 大小: $([math]::Round($totalSize/1MB, 2)) MB"
|
||||
Write-Host " 文件: $fileCount 个"
|
||||
|
||||
# ---------- 5. 部署提示 ----------
|
||||
Write-Host "`n[5/5] 后续操作:" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
Write-Host " 将 $DistDir 目录内容上传到服务器 Nginx 根目录"
|
||||
Write-Host " 然后在服务器执行: nginx -s reload"
|
||||
Write-Host ""
|
||||
Write-Host "==========================================" -ForegroundColor Cyan
|
||||
Write-Host " 构建完成!" -ForegroundColor Green
|
||||
Write-Host "==========================================" -ForegroundColor Cyan
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/bin/bash
|
||||
# ============================================================
|
||||
# HealthLink-HIS 前端部署脚本
|
||||
# 用法: bash deploy-frontend.sh [prod|test|staging|dev]
|
||||
# 默认: prod
|
||||
# ============================================================
|
||||
set -e
|
||||
|
||||
MODE=${1:-prod}
|
||||
PROJECT_DIR=$(cd "$(dirname "$0")/.." && pwd)
|
||||
UI_DIR="$PROJECT_DIR/healthlink-his-ui"
|
||||
DIST_DIR="$UI_DIR/dist"
|
||||
|
||||
echo "=========================================="
|
||||
echo " HealthLink-HIS 前端部署"
|
||||
echo " 环境: $MODE"
|
||||
echo " 目录: $UI_DIR"
|
||||
echo "=========================================="
|
||||
|
||||
# ---------- 1. 环境检查 ----------
|
||||
echo ""
|
||||
echo "[1/5] 环境检查..."
|
||||
|
||||
check_cmd() {
|
||||
if ! command -v "$1" &> /dev/null; then
|
||||
echo "错误: 未找到 $1,请先安装"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_cmd node
|
||||
check_cmd npm
|
||||
|
||||
NODE_VER=$(node -v | sed 's/v//' | cut -d. -f1)
|
||||
if [ "$NODE_VER" -lt 18 ]; then
|
||||
echo "错误: Node.js 版本需要 >= 18,当前: $(node -v)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo " Node.js: $(node -v) ✓"
|
||||
echo " npm: $(npm -v) ✓"
|
||||
|
||||
# ---------- 2. 安装依赖 ----------
|
||||
echo ""
|
||||
echo "[2/5] 安装依赖..."
|
||||
cd "$UI_DIR"
|
||||
|
||||
# 清理旧的 node_modules(可选,取消注释启用)
|
||||
# echo " 清理旧依赖..."
|
||||
# rm -rf node_modules package-lock.json
|
||||
|
||||
npm install --production=false --legacy-peer-deps
|
||||
echo " 依赖安装完成 ✓"
|
||||
|
||||
# ---------- 3. 构建 ----------
|
||||
echo ""
|
||||
echo "[3/5] 构建 ($MODE)..."
|
||||
npm run "build:$MODE"
|
||||
echo " 构建完成 ✓"
|
||||
|
||||
# ---------- 4. 产物信息 ----------
|
||||
echo ""
|
||||
echo "[4/5] 构建产物:"
|
||||
TOTAL_SIZE=$(du -sh "$DIST_DIR" 2>/dev/null | cut -f1)
|
||||
FILE_COUNT=$(find "$DIST_DIR" -type f | wc -l)
|
||||
echo " 路径: $DIST_DIR"
|
||||
echo " 大小: $TOTAL_SIZE"
|
||||
echo " 文件: $FILE_COUNT 个"
|
||||
|
||||
# ---------- 5. 部署提示 ----------
|
||||
echo ""
|
||||
echo "[5/5] 部署方式:"
|
||||
echo ""
|
||||
echo " 方式一: 复制到 Nginx"
|
||||
echo " cp -r $DIST_DIR/* /usr/share/nginx/html/healthlink-his/"
|
||||
echo " nginx -s reload"
|
||||
echo ""
|
||||
echo " 方式二: 软链接(推荐,方便更新)"
|
||||
echo " ln -sfn $DIST_DIR /usr/share/nginx/html/healthlink-his"
|
||||
echo " nginx -s reload"
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " 部署完成!"
|
||||
echo "=========================================="
|
||||
@@ -1,81 +0,0 @@
|
||||
# ============================================================
|
||||
# HealthLink-HIS 前端依赖问题排查与修复脚本
|
||||
# 用法: bash fix-deps.sh
|
||||
# ============================================================
|
||||
set -e
|
||||
|
||||
PROJECT_DIR=$(cd "$(dirname "$0")/.." && pwd)
|
||||
UI_DIR="$PROJECT_DIR/healthlink-his-ui"
|
||||
|
||||
cd "$UI_DIR"
|
||||
|
||||
echo "=========================================="
|
||||
echo " HealthLink-HIS 前端依赖诊断"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
# 检查 node_modules 是否存在
|
||||
if [ ! -d "node_modules" ]; then
|
||||
echo "[!] node_modules 不存在,执行 npm install..."
|
||||
npm install --legacy-peer-deps
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 检查 package-lock.json 是否存在
|
||||
if [ ! -f "package-lock.json" ]; then
|
||||
echo "[!] package-lock.json 缺失,重新生成..."
|
||||
npm install --legacy-peer-deps
|
||||
fi
|
||||
|
||||
# 检查关键依赖
|
||||
echo "检查关键依赖:"
|
||||
DEPS=("vue" "vite" "vxe-table" "element-plus" "pinia" "vue-router" "axios" "dayjs")
|
||||
for dep in "${DEPS[@]}"; do
|
||||
if [ -d "node_modules/$dep" ]; then
|
||||
VER=$(node -p "require('./node_modules/$dep/package.json').version" 2>/dev/null || echo "未知")
|
||||
echo " ✓ $dep@$VER"
|
||||
else
|
||||
echo " ✗ $dep 缺失!"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
# 检查过时依赖
|
||||
echo "检查过时依赖 (可选升级):"
|
||||
npm outdated 2>/dev/null || true
|
||||
|
||||
echo ""
|
||||
|
||||
# 常见问题修复菜单
|
||||
echo "=========================================="
|
||||
echo " 修复选项:"
|
||||
echo " 1) 重新安装依赖 (rm node_modules + npm install)"
|
||||
echo " 2) 清理缓存并重装 (npm cache clean + 重装)"
|
||||
echo " 3) 修复 peer 依赖冲突 (npm install --legacy-peer-deps)"
|
||||
echo " 4) 退出"
|
||||
echo "=========================================="
|
||||
read -p "选择 [1-4]: " choice
|
||||
|
||||
case $choice in
|
||||
1)
|
||||
echo "清理 node_modules..."
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install --legacy-peer-deps
|
||||
;;
|
||||
2)
|
||||
echo "清理缓存..."
|
||||
npm cache clean --force
|
||||
rm -rf node_modules package-lock.json
|
||||
npm install --legacy-peer-deps
|
||||
;;
|
||||
3)
|
||||
npm install --legacy-peer-deps
|
||||
;;
|
||||
*)
|
||||
echo "退出"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "完成 ✓"
|
||||
@@ -1,48 +0,0 @@
|
||||
# ============================================================
|
||||
# HealthLink-HIS 前端 Nginx 配置
|
||||
# 放到 /etc/nginx/conf.d/openhis.conf 或 include 到 nginx.conf
|
||||
# ============================================================
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name healthlink-his.local; # 改成实际域名或 IP
|
||||
|
||||
# 前端静态文件
|
||||
location / {
|
||||
root /usr/share/nginx/html/healthlink-his;
|
||||
index index.html;
|
||||
try_files $uri $uri/ /index.html; # SPA 路由回退
|
||||
}
|
||||
|
||||
# 后端 API 代理
|
||||
location /prd-api/ {
|
||||
proxy_pass http://127.0.0.1:18082/healthlink-his/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_connect_timeout 300;
|
||||
proxy_read_timeout 300;
|
||||
client_max_body_size 50m;
|
||||
}
|
||||
|
||||
# gzip 压缩(Vite 构建已生成 .gz 文件,Nginx 直接发送)
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
|
||||
gzip_min_length 1024;
|
||||
gzip_comp_level 6;
|
||||
gzip_vary on;
|
||||
|
||||
# 静态资源缓存(带 hash 的文件长期缓存)
|
||||
location ~* /assets/.*\.(js|css|woff2?|ttf|eot|png|jpg|jpeg|gif|svg|ico)$ {
|
||||
root /usr/share/nginx/html/healthlink-his;
|
||||
expires 365d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# index.html 不缓存(保证更新及时生效)
|
||||
location = /index.html {
|
||||
root /usr/share/nginx/html/healthlink-his;
|
||||
add_header Cache-Control "no-cache, no-store, must-revalidate";
|
||||
}
|
||||
}
|
||||
1
healthlink-his-server/.mvn/jvm.config
Normal file
1
healthlink-his-server/.mvn/jvm.config
Normal file
@@ -0,0 +1 @@
|
||||
--sun-misc-unsafe-memory-access=allow
|
||||
@@ -6,6 +6,9 @@ import com.core.common.core.domain.entity.SysDictData;
|
||||
import com.core.common.core.redis.RedisCache;
|
||||
import com.core.common.utils.spring.SpringUtils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
@@ -15,6 +18,7 @@ import java.util.List;
|
||||
* @author system
|
||||
*/
|
||||
public class DictUtils {
|
||||
private static final Logger log = LoggerFactory.getLogger(DictUtils.class);
|
||||
/**
|
||||
* 分隔符
|
||||
*/
|
||||
@@ -37,11 +41,39 @@ public class DictUtils {
|
||||
* @return dictDatas 字典数据列表
|
||||
*/
|
||||
public static List<SysDictData> getDictCache(String key) {
|
||||
JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
|
||||
if (StringUtils.isNotNull(arrayCache)) {
|
||||
return arrayCache.toList(SysDictData.class);
|
||||
try {
|
||||
Object cached = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
|
||||
if (cached == null) {
|
||||
return null;
|
||||
}
|
||||
if (cached instanceof JSONArray arrayCache) {
|
||||
return arrayCache.toList(SysDictData.class);
|
||||
}
|
||||
if (cached instanceof List<?> list) {
|
||||
// Redis缓存可能已反序列化为List,尝试逐个转换
|
||||
java.util.ArrayList<SysDictData> result = new java.util.ArrayList<>(list.size());
|
||||
for (Object item : list) {
|
||||
if (item instanceof SysDictData dictData) {
|
||||
result.add(dictData);
|
||||
} else {
|
||||
// 尝试通过JSON转换
|
||||
String json = com.alibaba.fastjson2.JSON.toJSONString(item);
|
||||
result.add(com.alibaba.fastjson2.JSON.parseObject(json, SysDictData.class));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
log.warn("字典缓存key={}的数据类型异常: {}, 清除缓存", key, cached.getClass().getName());
|
||||
removeDictCache(key);
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.warn("获取字典缓存异常key={}, 清除缓存: {}", key, e.getMessage());
|
||||
try {
|
||||
removeDictCache(key);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package com.core.framework.config;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
@@ -19,65 +16,36 @@ import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* 程序注解配置
|
||||
*
|
||||
* @author system
|
||||
*/
|
||||
@Configuration
|
||||
// 表示通过aop框架暴露该代理对象,AopContext能够访问
|
||||
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||
// 指定要扫描的Mapper类的包的路径
|
||||
@MapperScan({"com.core.**.mapper", "com.healthlink.his.**.mapper"})
|
||||
public class ApplicationConfig {
|
||||
private static final Logger log = LoggerFactory.getLogger(ApplicationConfig.class);
|
||||
|
||||
/** 支持多种日期格式的反序列化器 */
|
||||
private static final JsonDeserializer<LocalDateTime> LOCAL_DATE_TIME_DESERIALIZER = new JsonDeserializer<LocalDateTime>() {
|
||||
private static final JsonDeserializer<LocalDateTime> LOCAL_DATE_TIME_DESERIALIZER = new JsonDeserializer<>() {
|
||||
private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||
private static final DateTimeFormatter SIMPLE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
private static final DateTimeFormatter SLASH_FORMATTER = DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss");
|
||||
|
||||
@Override
|
||||
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||
public LocalDateTime deserialize(JsonParser p, DeserializationContext context) throws IOException {
|
||||
String text = p.getText();
|
||||
if (text == null || text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
// 去除时区后缀 Z/z 和偏移量 +HH:MM/+HHMM(LocalDateTime 不含时区信息)
|
||||
if (text == null || text.isEmpty()) return null;
|
||||
String cleaned = text.replaceAll("[Zz]$", "").replaceAll("[+-]\\d{2}:?\\d{2}$", "");
|
||||
// 尝试 ISO 8601 格式(yyyy-MM-ddTHH:mm:ss.SSS)
|
||||
try {
|
||||
return LocalDateTime.parse(cleaned, ISO_FORMATTER);
|
||||
} catch (Exception ignored) {
|
||||
// intentionally ignored
|
||||
}
|
||||
// 尝试简单格式(yyyy-MM-dd HH:mm:ss)
|
||||
try {
|
||||
return LocalDateTime.parse(cleaned, SIMPLE_FORMATTER);
|
||||
} catch (Exception ignored) {
|
||||
// intentionally ignored
|
||||
}
|
||||
// 尝试斜杠格式(yyyy/M/d HH:mm:ss)
|
||||
try { return LocalDateTime.parse(cleaned, ISO_FORMATTER); } catch (Exception ignored) {}
|
||||
try { return LocalDateTime.parse(cleaned, SIMPLE_FORMATTER); } catch (Exception ignored) {}
|
||||
return LocalDateTime.parse(cleaned, SLASH_FORMATTER);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 时区配置
|
||||
*/
|
||||
@Bean
|
||||
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
|
||||
return builder -> {
|
||||
// 设置默认时区
|
||||
builder.timeZone(TimeZone.getDefault());
|
||||
// 设置日期格式为 yyyy/M/d HH:mm:ss,支持多种格式反序列化
|
||||
builder.simpleDateFormat("yyyy/M/d HH:mm:ss");
|
||||
// 添加JavaTimeModule支持,用于LocalDateTime
|
||||
builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||
javaTimeModule.addDeserializer(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER);
|
||||
builder.modules(javaTimeModule);
|
||||
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss")));
|
||||
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Web Layer - API Controllers
|
||||
|
||||
**Module**: `openhis-application/web`
|
||||
**Module**: `healthlink-his-application/web`
|
||||
**Role**: API endpoint layer - all REST controllers for frontend communication
|
||||
|
||||
## OVERVIEW
|
||||
|
||||
@@ -153,7 +153,7 @@ public class TicketAppServiceImpl implements ITicketAppService {
|
||||
dto.setIdCard(raw.getIdCard());
|
||||
dto.setDoctorId(raw.getDoctorId());
|
||||
dto.setDepartmentId(raw.getDepartmentId());
|
||||
dto.setRealPatientId(raw.getPatientId());
|
||||
dto.setRealPatientId(raw.getRealPatientId() != null ? raw.getRealPatientId() : raw.getPatientId());
|
||||
dto.setOrderId(raw.getOrderId());
|
||||
dto.setOrderNo(raw.getOrderNo());
|
||||
|
||||
|
||||
@@ -515,29 +515,28 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra
|
||||
// 构建查询条件
|
||||
QueryWrapper<CurrentDayEncounterDto> queryWrapper = HisQueryUtils.buildQueryWrapper(null, searchKey,
|
||||
new HashSet<>(Arrays.asList("patient_name", "organization_name", "practitioner_name", "healthcare_name", "identifier_no")),
|
||||
request);
|
||||
null); // registerTimeSTime/ETime 已下推到 SQL 内层 WHERE,跳过 buildQueryWrapper 的自动 *STime/*ETime 处理
|
||||
|
||||
// 手动处理 statusEnum 参数(用于过滤退号记录)
|
||||
// 提取statusEnum参数,下推到内层WHERE(避免外层重复过滤)
|
||||
Integer statusFilter = null;
|
||||
String statusEnumParam = request.getParameter("statusEnum");
|
||||
if (statusEnumParam != null && !statusEnumParam.isEmpty()) {
|
||||
try {
|
||||
Integer statusEnum = Integer.parseInt(statusEnumParam);
|
||||
if (statusEnum == -1) {
|
||||
// -1 表示排除退号记录(正常挂号)
|
||||
queryWrapper.ne("status_enum", 6);
|
||||
} else {
|
||||
// 其他值表示精确匹配
|
||||
queryWrapper.eq("status_enum", statusEnum);
|
||||
}
|
||||
statusFilter = Integer.parseInt(statusEnumParam);
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略无效的参数值
|
||||
}
|
||||
}
|
||||
|
||||
// 提取日期范围参数,下推到内层WHERE以优化性能(避免全表JOIN后再过滤)
|
||||
String registerTimeSTime = request.getParameter("registerTimeSTime");
|
||||
String registerTimeETime = request.getParameter("registerTimeETime");
|
||||
|
||||
IPage<CurrentDayEncounterDto> currentDayEncounter = outpatientRegistrationAppMapper.getCurrentDayEncounter(
|
||||
new Page<>(pageNo, pageSize), EncounterClass.AMB.getValue(), EncounterStatus.IN_PROGRESS.getValue(),
|
||||
ParticipantType.ADMITTER.getCode(), ParticipantType.REGISTRATION_DOCTOR.getCode(), queryWrapper,
|
||||
ChargeItemContext.REGISTER.getValue(), PaymentStatus.SUCCESS.getValue());
|
||||
ChargeItemContext.REGISTER.getValue(), PaymentStatus.SUCCESS.getValue(),
|
||||
registerTimeSTime, registerTimeETime, statusFilter);
|
||||
|
||||
// 过滤候选池排除列表
|
||||
// 仅当调用方显式传 excludeFromCandidatePool=true 时才过滤,避免非分诊场景(挂号/收费)
|
||||
|
||||
@@ -54,7 +54,10 @@ public interface OutpatientRegistrationAppMapper {
|
||||
@Param("classEnum") Integer classEnum, @Param("statusEnum") Integer statusEnum,
|
||||
@Param("participantType1") String participantType1, @Param("participantType2") String participantType2,
|
||||
@Param(Constants.WRAPPER) QueryWrapper<CurrentDayEncounterDto> queryWrapper,
|
||||
@Param("register") Integer register, @Param("paymentStatus") Integer paymentStatus);
|
||||
@Param("register") Integer register, @Param("paymentStatus") Integer paymentStatus,
|
||||
@Param("registerTimeSTime") String registerTimeSTime,
|
||||
@Param("registerTimeETime") String registerTimeETime,
|
||||
@Param("statusFilter") Integer statusFilter);
|
||||
|
||||
/**
|
||||
* 查询item绑定的信息(耗材或诊疗)
|
||||
|
||||
@@ -169,6 +169,9 @@ public class ExamApplyController extends BaseController {
|
||||
examApply.setApplyTime(LocalDateTime.now());
|
||||
examApply.setCreateTime(new Date());
|
||||
examApply.setApplyStatus(0); // 0=已开单
|
||||
if (examApply.getIsCharged() == null) examApply.setIsCharged(0);
|
||||
if (examApply.getIsRefunded() == null) examApply.setIsRefunded(0);
|
||||
if (examApply.getIsExecuted() == null) examApply.setIsExecuted(0);
|
||||
|
||||
// 操作员工号取当前登录用户
|
||||
try {
|
||||
|
||||
@@ -84,6 +84,15 @@ public class ExamApplyDto implements Serializable {
|
||||
/** 申请单状态 0已开单 1已收费 2已预约 3已签到 4部分报告 5已完告 6作废 */
|
||||
private Integer applyStatus;
|
||||
|
||||
/** 是否已收费 0=否 1=是 */
|
||||
private Integer isCharged;
|
||||
|
||||
/** 是否已退费 0=否 1=是 */
|
||||
private Integer isRefunded;
|
||||
|
||||
/** 是否已执行 0=否 1=是 */
|
||||
private Integer isExecuted;
|
||||
|
||||
/** 就诊ID(用于写入门诊医嘱和费用项关联) */
|
||||
private Long encounterId;
|
||||
|
||||
|
||||
@@ -1197,11 +1197,27 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
if (firstTimeSave) {
|
||||
medRequestIdList.add(medicationRequest.getId().toString());
|
||||
}
|
||||
// Bug #666 fix: 签发时也需要确保MedicationDispense记录存在
|
||||
// 直接签发(不先保存)不创建MedicationDispense,导致药房发药页面查不到患者信息
|
||||
Long dispenseId = null;
|
||||
if (is_save) {
|
||||
// 处理药品发放
|
||||
Long dispenseId = iMedicationDispenseService.handleMedicationDispense(medicationRequest,
|
||||
// 保存时创建药品发放记录
|
||||
dispenseId = iMedicationDispenseService.handleMedicationDispense(medicationRequest,
|
||||
adviceSaveDto.getDbOpType());
|
||||
|
||||
} else if (is_sign) {
|
||||
// 签发时检查是否已存在MedicationDispense,不存在则创建
|
||||
List<MedicationDispense> existingDispenses = iMedicationDispenseService.selectByRequestIdList(
|
||||
java.util.List.of(medicationRequest.getId()));
|
||||
if (existingDispenses.isEmpty()) {
|
||||
dispenseId = iMedicationDispenseService.handleMedicationDispense(medicationRequest,
|
||||
DbOpType.INSERT.getCode());
|
||||
log.info("Bug #666: 签发时创建MedicationDispense, medReqId={}, dispenseId={}",
|
||||
medicationRequest.getId(), dispenseId);
|
||||
} else {
|
||||
dispenseId = existingDispenses.get(0).getId();
|
||||
}
|
||||
}
|
||||
if (is_save || is_sign) {
|
||||
// 保存药品费用项
|
||||
chargeItem = new ChargeItem();
|
||||
chargeItem.setId(adviceSaveDto.getChargeItemId()); // 费用项id
|
||||
@@ -1451,7 +1467,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
// 保存操作
|
||||
boolean is_save = AdviceOpType.SAVE_ADVICE.getCode().equals(adviceOpType);
|
||||
// 签发操作
|
||||
// boolean is_sign = AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType);
|
||||
boolean is_sign = AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType);
|
||||
DeviceRequest deviceRequest;
|
||||
// 声明费用项
|
||||
ChargeItem chargeItem;
|
||||
@@ -1659,11 +1675,27 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
||||
deviceRequest.setContentJson(injectRemarkIntoContentJson(deviceRequest.getContentJson(), adviceSaveDto.getRemark()));
|
||||
}
|
||||
iDeviceRequestService.saveOrUpdate(deviceRequest);
|
||||
// Bug #666 fix: 签发时也需要确保DeviceDispense记录存在
|
||||
Long dispenseId = null;
|
||||
if (is_save) {
|
||||
// 处理耗材发放
|
||||
Long dispenseId = iDeviceDispenseService.handleDeviceDispense(deviceRequest,
|
||||
// 保存时创建耗材发放记录
|
||||
dispenseId = iDeviceDispenseService.handleDeviceDispense(deviceRequest,
|
||||
adviceSaveDto.getDbOpType());
|
||||
|
||||
} else if (is_sign) {
|
||||
// 签发时检查是否已存在DeviceDispense,不存在则创建
|
||||
List<com.healthlink.his.workflow.domain.DeviceDispense> existingDeviceDispenses =
|
||||
iDeviceDispenseService.selectByRequestIdList(
|
||||
java.util.List.of(deviceRequest.getId()));
|
||||
if (existingDeviceDispenses.isEmpty()) {
|
||||
dispenseId = iDeviceDispenseService.handleDeviceDispense(deviceRequest,
|
||||
DbOpType.INSERT.getCode());
|
||||
log.info("Bug #666: 签发时创建DeviceDispense, deviceReqId={}, dispenseId={}",
|
||||
deviceRequest.getId(), dispenseId);
|
||||
} else {
|
||||
dispenseId = existingDeviceDispenses.get(0).getId();
|
||||
}
|
||||
}
|
||||
if (is_save || is_sign) {
|
||||
// 保存耗材费用项
|
||||
chargeItem = new ChargeItem();
|
||||
chargeItem.setId(adviceSaveDto.getChargeItemId()); // 费用项 id
|
||||
|
||||
@@ -451,30 +451,49 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
|
||||
// 删除费用项
|
||||
iChargeItemService.deleteByServiceTableAndId(CommonConstants.TableName.MED_MEDICATION_REQUEST,
|
||||
adviceSaveDto.getRequestId());
|
||||
// 删除代煎费
|
||||
iChargeItemService.remove(new LambdaQueryWrapper<ChargeItem>()
|
||||
.eq(ChargeItem::getPrescriptionNo, adviceSaveDto.getPrescriptionNo())
|
||||
.eq(ChargeItem::getProductId, sufferingDefinitionId));
|
||||
// 删除代煎费(按处方号精确清理)
|
||||
if (adviceSaveDto.getPrescriptionNo() != null) {
|
||||
iChargeItemService.remove(new LambdaQueryWrapper<ChargeItem>()
|
||||
.eq(ChargeItem::getPrescriptionNo, adviceSaveDto.getPrescriptionNo())
|
||||
.eq(ChargeItem::getProductId, sufferingDefinitionId));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (is_sign) {
|
||||
// 按groupId分组
|
||||
Map<Long, List<AdviceSaveDto>> groupMap
|
||||
= insertOrUpdateList.stream().collect(Collectors.groupingBy(AdviceSaveDto::getGroupId));
|
||||
// 为每个分组生成唯一的处方号
|
||||
groupMap.forEach((groupId, groupList) -> {
|
||||
// 先查询当前groupId是否已经被签发生成过处方号
|
||||
List<MedicationRequest> list = iMedicationRequestService
|
||||
.list(new LambdaQueryWrapper<MedicationRequest>().eq(MedicationRequest::getGroupId, groupId));
|
||||
if (!list.isEmpty() && StringUtils.isNotEmpty(list.get(0).getPrescriptionNo())) {
|
||||
groupList.forEach(dto -> dto.setPrescriptionNo(list.get(0).getPrescriptionNo()));
|
||||
} else {
|
||||
String prescriptionNo
|
||||
= assignSeqUtil.getSeq(AssignSeqEnum.PRESCRIPTION_CHINESE_HERBAL_MEDICINE.getPrefix(), 8);
|
||||
groupList.forEach(dto -> dto.setPrescriptionNo(prescriptionNo));
|
||||
// 有 groupId 的按组生成处方号(groupingBy 不接受 null key,先过滤)
|
||||
insertOrUpdateList.stream()
|
||||
.filter(e -> e.getGroupId() != null)
|
||||
.collect(Collectors.groupingBy(AdviceSaveDto::getGroupId))
|
||||
.forEach((groupId, groupList) -> {
|
||||
// 先查询当前groupId是否已经被签发生成过处方号
|
||||
List<MedicationRequest> list = iMedicationRequestService
|
||||
.list(new LambdaQueryWrapper<MedicationRequest>()
|
||||
.eq(MedicationRequest::getGroupId, groupId));
|
||||
if (!list.isEmpty() && StringUtils.isNotEmpty(list.get(0).getPrescriptionNo())) {
|
||||
groupList.forEach(dto -> dto.setPrescriptionNo(list.get(0).getPrescriptionNo()));
|
||||
} else {
|
||||
String prescriptionNo = assignSeqUtil.getSeq(
|
||||
AssignSeqEnum.PRESCRIPTION_CHINESE_HERBAL_MEDICINE.getPrefix(), 8);
|
||||
groupList.forEach(dto -> dto.setPrescriptionNo(prescriptionNo));
|
||||
}
|
||||
});
|
||||
|
||||
// 无 groupId 的各自生成处方号
|
||||
for (AdviceSaveDto dto : insertOrUpdateList) {
|
||||
if (dto.getGroupId() != null) {
|
||||
continue;
|
||||
}
|
||||
});
|
||||
if (dto.getRequestId() != null) {
|
||||
MedicationRequest existing = iMedicationRequestService.getById(dto.getRequestId());
|
||||
if (existing != null && StringUtils.isNotEmpty(existing.getPrescriptionNo())) {
|
||||
dto.setPrescriptionNo(existing.getPrescriptionNo());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
dto.setPrescriptionNo(assignSeqUtil.getSeq(
|
||||
AssignSeqEnum.PRESCRIPTION_CHINESE_HERBAL_MEDICINE.getPrefix(), 8));
|
||||
}
|
||||
}
|
||||
|
||||
// 医嘱签发编码
|
||||
@@ -597,8 +616,12 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
|
||||
Long encounterDiagnosisId = medicineList.get(0).getEncounterDiagnosisId();
|
||||
// 中药付数
|
||||
BigDecimal chineseHerbsDoseQuantity = medicineList.get(0).getChineseHerbsDoseQuantity();
|
||||
// 处方号
|
||||
String prescriptionNo = insertOrUpdateList.get(0).getPrescriptionNo();
|
||||
// 收集所有处方号(不同分组可能有不同处方号)
|
||||
List<String> prescriptionNos = insertOrUpdateList.stream()
|
||||
.map(AdviceSaveDto::getPrescriptionNo)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 签发时,生成中药代煎的账单
|
||||
if (Whether.YES.getValue().equals(sufferingFlag) && is_sign) {
|
||||
@@ -607,9 +630,10 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
|
||||
AdviceBaseDto adviceBaseDto = new AdviceBaseDto();
|
||||
adviceBaseDto.setAdviceDefinitionId(sufferingDefinitionId); // 医嘱定义id
|
||||
|
||||
// 先删除中药代煎的账单
|
||||
// 先删除该就诊关联的所有中药代煎账单
|
||||
iChargeItemService.remove(new LambdaQueryWrapper<ChargeItem>()
|
||||
.eq(ChargeItem::getPrescriptionNo, prescriptionNo).eq(ChargeItem::getProductId, sufferingDefinitionId));
|
||||
.eq(ChargeItem::getEncounterId, encounterId)
|
||||
.eq(ChargeItem::getProductId, sufferingDefinitionId));
|
||||
|
||||
// 对应的诊疗医嘱信息
|
||||
AdviceBaseDto activityAdviceBaseDto = iDoctorStationAdviceAppService.getAdviceBaseInfo(adviceBaseDto, null,
|
||||
@@ -618,40 +642,42 @@ public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStation
|
||||
// 费用定价
|
||||
AdvicePriceDto advicePriceDto = activityAdviceBaseDto.getPriceList().get(0);
|
||||
if (advicePriceDto != null) {
|
||||
// 生成账单
|
||||
chargeItem = new ChargeItem();
|
||||
chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
|
||||
chargeItem.setPrescriptionNo(prescriptionNo); // 处方号
|
||||
chargeItem.setStatusEnum(ChargeItemStatus.PLANNED.getValue()); // 收费状态
|
||||
chargeItem.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix(), 4));
|
||||
chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
|
||||
chargeItem.setPatientId(patientId); // 患者
|
||||
chargeItem.setContextEnum(ChargeItemContext.ACTIVITY.getValue()); // 类型
|
||||
chargeItem.setEncounterId(encounterId); // 就诊id
|
||||
chargeItem.setDefinitionId(advicePriceDto.getDefinitionId()); // 费用定价ID
|
||||
chargeItem.setEntererId(SecurityUtils.getLoginUser().getPractitionerId());// 开立人ID
|
||||
chargeItem.setRequestingOrgId(orgId); // 开立科室
|
||||
chargeItem.setEnteredDate(curDate); // 开立时间
|
||||
chargeItem.setProductTable(activityAdviceBaseDto.getAdviceTableName());// 产品所在表
|
||||
chargeItem.setProductId(activityAdviceBaseDto.getAdviceDefinitionId());// 收费项id
|
||||
chargeItem.setAccountId(accountId);// 关联账户ID
|
||||
chargeItem.setConditionId(conditionId); // 诊断id
|
||||
chargeItem.setEncounterDiagnosisId(encounterDiagnosisId); // 就诊诊断id
|
||||
// 为每个处方号分别生成代煎账单
|
||||
for (String prescriptionNo : prescriptionNos) {
|
||||
chargeItem = new ChargeItem();
|
||||
chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
|
||||
chargeItem.setPrescriptionNo(prescriptionNo); // 处方号
|
||||
chargeItem.setStatusEnum(ChargeItemStatus.PLANNED.getValue()); // 收费状态
|
||||
chargeItem.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix(), 4));
|
||||
chargeItem.setPatientId(patientId); // 患者
|
||||
chargeItem.setContextEnum(ChargeItemContext.ACTIVITY.getValue()); // 类型
|
||||
chargeItem.setEncounterId(encounterId); // 就诊id
|
||||
chargeItem.setDefinitionId(advicePriceDto.getDefinitionId()); // 费用定价ID
|
||||
chargeItem.setEntererId(SecurityUtils.getLoginUser().getPractitionerId());// 开立人ID
|
||||
chargeItem.setRequestingOrgId(orgId); // 开立科室
|
||||
chargeItem.setEnteredDate(curDate); // 开立时间
|
||||
chargeItem.setProductTable(activityAdviceBaseDto.getAdviceTableName());// 产品所在表
|
||||
chargeItem.setProductId(activityAdviceBaseDto.getAdviceDefinitionId());// 收费项id
|
||||
chargeItem.setAccountId(accountId);// 关联账户ID
|
||||
chargeItem.setConditionId(conditionId); // 诊断id
|
||||
chargeItem.setEncounterDiagnosisId(encounterDiagnosisId); // 就诊诊断id
|
||||
|
||||
chargeItem.setQuantityValue(quantity); // 数量
|
||||
chargeItem.setQuantityUnit(activityAdviceBaseDto.getUnitCode()); // 单位
|
||||
chargeItem.setUnitPrice(advicePriceDto.getPrice()); // 单价
|
||||
// 计算总价,保留6位小数
|
||||
BigDecimal qty = quantity;
|
||||
chargeItem.setTotalPrice(qty.multiply(advicePriceDto.getPrice()).setScale(6, RoundingMode.HALF_UP)); // 总价
|
||||
chargeItem.setTcmFlag(Whether.YES.getValue());// 中医标识
|
||||
iChargeItemService.save(chargeItem);
|
||||
chargeItem.setQuantityValue(quantity); // 数量
|
||||
chargeItem.setQuantityUnit(activityAdviceBaseDto.getUnitCode()); // 单位
|
||||
chargeItem.setUnitPrice(advicePriceDto.getPrice()); // 单价
|
||||
// 计算总价,保留6位小数
|
||||
BigDecimal qty = quantity;
|
||||
chargeItem.setTotalPrice(qty.multiply(advicePriceDto.getPrice()).setScale(6, RoundingMode.HALF_UP)); // 总价
|
||||
chargeItem.setTcmFlag(Whether.YES.getValue());// 中医标识
|
||||
iChargeItemService.save(chargeItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Whether.NO.getValue().equals(sufferingFlag)) {
|
||||
// 删除中药代煎的账单
|
||||
// 删除该就诊关联的所有中药代煎账单
|
||||
iChargeItemService.remove(new LambdaQueryWrapper<ChargeItem>()
|
||||
.eq(ChargeItem::getPrescriptionNo, prescriptionNo).eq(ChargeItem::getProductId, sufferingDefinitionId));
|
||||
.eq(ChargeItem::getEncounterId, encounterId)
|
||||
.eq(ChargeItem::getProductId, sufferingDefinitionId));
|
||||
}
|
||||
|
||||
// 签发时,把草稿状态的账单更新为待收费[中医]
|
||||
|
||||
@@ -251,18 +251,16 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
||||
|
||||
// 遍历检验申请单明细,为每个检验项目创建对应的门诊医嘱记录
|
||||
for (DoctorStationLabApplyItemDto labApplyItemDto : doctorStationLabApplyDto.getLabApplyItemList()) {
|
||||
// 1. 根据检验项目名称查询诊疗定义(检验项目)
|
||||
// 1. Bug #764: 使用 lab_activity_definition 表的 activityId 查询检验项目定义
|
||||
// 检验项目存储在 lab_activity_definition 独立表中,不走 wor_activity_definition
|
||||
String itemName = labApplyItemDto.getItemName();
|
||||
Long activityDefinitionId = activityDefinitionService.getAppointActivityDefinitionId(itemName);
|
||||
|
||||
if (activityDefinitionId == null) {
|
||||
throw new RuntimeException("未找到检验项目 '" + itemName + "' 对应的诊疗定义");
|
||||
Long labActivityId = labApplyItemDto.getActivityId();
|
||||
if (labActivityId == null) {
|
||||
throw new RuntimeException("检验项目 '" + itemName + "' 未传入 activityId,请重新选择检验项目");
|
||||
}
|
||||
|
||||
// 2. 获取诊疗定义详情
|
||||
ActivityDefinition activityDefinition = activityDefinitionService.getById(activityDefinitionId);
|
||||
if (activityDefinition == null) {
|
||||
throw new RuntimeException("诊疗定义不存在");
|
||||
LabActivityDefinition labActivityDef = labActivityDefinitionService.getById(labActivityId);
|
||||
if (labActivityDef == null) {
|
||||
throw new RuntimeException("检验项目 '" + itemName + "' 对应的检验项目定义不存在(ID: " + labActivityId + ")");
|
||||
}
|
||||
|
||||
// 3. 根据执行科室代码获取科室 ID(positionId)
|
||||
@@ -297,17 +295,17 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
||||
|
||||
// 设置检验项目相关信息
|
||||
// 医嘱定义 ID(诊疗定义 ID)
|
||||
adviceSaveDto.setAdviceDefinitionId(activityDefinitionId);
|
||||
adviceSaveDto.setAdviceDefinitionId(labActivityId);
|
||||
// 费用定价主表 ID(对应 adm_charge_item 表的 definition_id 字段)
|
||||
adviceSaveDto.setDefinitionId(activityDefinitionId);
|
||||
adviceSaveDto.setDefinitionId(labActivityId);
|
||||
// 医嘱名称
|
||||
adviceSaveDto.setAdviceName(itemName);
|
||||
// 医嘱详细分类
|
||||
adviceSaveDto.setCategoryCode(activityDefinition.getCategoryCode());
|
||||
adviceSaveDto.setCategoryCode(labActivityDef.getCategoryCode());
|
||||
// 活动 ID(诊疗定义 ID)
|
||||
adviceSaveDto.setActivityId(activityDefinitionId);
|
||||
adviceSaveDto.setActivityId(labActivityId);
|
||||
// 医嘱定义对应表名
|
||||
adviceSaveDto.setAdviceTableName("wor_activity_definition");
|
||||
adviceSaveDto.setAdviceTableName("lab_activity_definition");
|
||||
// 执行科室 ID
|
||||
adviceSaveDto.setPositionId(positionId);
|
||||
|
||||
@@ -346,13 +344,13 @@ public class DoctorStationLabApplyServiceImpl implements IDoctorStationInspectio
|
||||
// 请求数量
|
||||
adviceSaveDto.setQuantity(labApplyItemDto.getItemQty() != null ? labApplyItemDto.getItemQty() : java.math.BigDecimal.ONE);
|
||||
// 请求单位编码(使用诊疗定义的使用单位)
|
||||
adviceSaveDto.setUnitCode(activityDefinition.getPermittedUnitCode());
|
||||
adviceSaveDto.setUnitCode(labActivityDef.getPermittedUnitCode());
|
||||
|
||||
// 单价处理(BugFix#CodeReview: 根据套餐ID从正确的数据源获取价格)
|
||||
// 套餐项目:从 inspection_basic_information 表获取 package_amount
|
||||
// 普通项目:使用前端传入的 itemPrice(已从诊疗项目获取)
|
||||
java.math.BigDecimal unitPrice;
|
||||
Long feePackageId = activityDefinition.getFeePackageId();
|
||||
Long feePackageId = labActivityDef.getFeePackageId();
|
||||
|
||||
if (feePackageId != null) {
|
||||
// 套餐项目:查询套餐价格
|
||||
|
||||
@@ -304,6 +304,9 @@ public class EmergencyController {
|
||||
@PostMapping("/green-channel/activate")
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> activateGreenChannel(@RequestBody EmergencyGreenChannel gc) {
|
||||
if (gc.getPatientId() == null) {
|
||||
return R.fail("患者ID不能为空,请选择患者后再激活绿色通道");
|
||||
}
|
||||
gc.setActivateTime(new Date());
|
||||
gc.setCreateTime(new Date());
|
||||
greenChannelService.save(gc);
|
||||
|
||||
@@ -72,8 +72,8 @@ public class StructuredEmrController {
|
||||
@GetMapping("/timeliness/statistics")
|
||||
@Operation(summary = "完成率统计")
|
||||
public R<Map<String, Object>> getCompletionStatistics(
|
||||
@RequestParam String startDate,
|
||||
@RequestParam String endDate) {
|
||||
@RequestParam(required = false) String startDate,
|
||||
@RequestParam(required = false) String endDate) {
|
||||
return R.ok(structuredEmrAppService.getCompletionStatistics(startDate, endDate));
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.healthlink.his.web.inhospitalcharge.dto.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -30,11 +31,15 @@ public interface IInHospitalRegisterAppService {
|
||||
* @param registeredFlag 已登记标识,已登记传 1 ,待登记传 0
|
||||
* @param pageNo 当前页
|
||||
* @param pageSize 每页多少条
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param organizationId 入院科室ID
|
||||
* @param request 请求
|
||||
* @return 住院登记信息
|
||||
*/
|
||||
IPage<InHospitalRegisterQueryDto> getRegisterInfo(InHospitalRegisterQueryDto inHospitalRegisterQueryDto,
|
||||
String searchKey, String registeredFlag, Integer pageNo, Integer pageSize, HttpServletRequest request);
|
||||
String searchKey, String registeredFlag, Integer pageNo, Integer pageSize,
|
||||
Date startTime, Date endTime, Long organizationId, HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* 查询患者基本信息
|
||||
@@ -99,4 +104,20 @@ public interface IInHospitalRegisterAppService {
|
||||
* @return 病区列表
|
||||
*/
|
||||
List<LocationDto> getWardList(Long orgId);
|
||||
|
||||
/**
|
||||
* 修改住院登记信息
|
||||
*
|
||||
* @param inHospitalInfoDto 登记dto
|
||||
* @return 结果
|
||||
*/
|
||||
R<?> updateRegistration(InHospitalInfoDto inHospitalInfoDto);
|
||||
|
||||
/**
|
||||
* 作废住院登记
|
||||
*
|
||||
* @param encounterId 住院就诊id
|
||||
* @return 结果
|
||||
*/
|
||||
R<?> voidRegistration(Long encounterId);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,9 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
|
||||
@Resource
|
||||
private YbManager ybManager;
|
||||
|
||||
@Resource
|
||||
private IChargeItemService iChargeItemService;
|
||||
|
||||
/**
|
||||
* 门诊医生开住院申请
|
||||
*
|
||||
@@ -170,16 +173,18 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
|
||||
*/
|
||||
@Override
|
||||
public IPage<InHospitalRegisterQueryDto> getRegisterInfo(InHospitalRegisterQueryDto inHospitalRegisterQueryDto,
|
||||
String searchKey, String registeredFlag, Integer pageNo, Integer pageSize, HttpServletRequest request) {
|
||||
String searchKey, String registeredFlag, Integer pageNo, Integer pageSize,
|
||||
Date startTime, Date endTime, Long organizationId, HttpServletRequest request) {
|
||||
Integer encounterStatus = EncounterZyStatus.TO_BE_REGISTERED.getValue(); // 待登记
|
||||
// 构建查询条件
|
||||
QueryWrapper<InHospitalRegisterQueryDto> queryWrapper
|
||||
= HisQueryUtils.buildQueryWrapper(inHospitalRegisterQueryDto, searchKey,
|
||||
new HashSet<>(Arrays.asList("registrar", "source_name", "patient_name")), request);
|
||||
new HashSet<>(Arrays.asList("registrar", "source_name", "patient_name", "id_card")), request);
|
||||
|
||||
IPage<InHospitalRegisterQueryDto> inHospitalRegisterInfo = inHospitalRegisterAppMapper
|
||||
.getInHospitalRegisterInfo(new Page<>(pageNo, pageSize), EncounterClass.IMP.getValue(), encounterStatus,
|
||||
registeredFlag, LocationForm.WARD.getValue(), queryWrapper);
|
||||
registeredFlag, LocationForm.WARD.getValue(), startTime, endTime, organizationId,
|
||||
queryWrapper);
|
||||
inHospitalRegisterInfo.getRecords().forEach(e -> {
|
||||
// 性别
|
||||
e.setGenderEnum_enumText(EnumUtils.getInfoByValue(AdministrativeGender.class, e.getGenderEnum()));
|
||||
@@ -362,6 +367,183 @@ public class InHospitalRegisterAppServiceImpl implements IInHospitalRegisterAppS
|
||||
return locationDtoList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改住院登记信息
|
||||
*
|
||||
* @param inHospitalInfoDto 登记dto
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public R<?> updateRegistration(InHospitalInfoDto inHospitalInfoDto) {
|
||||
Long encounterId = inHospitalInfoDto.getEncounterId();
|
||||
if (encounterId == null) {
|
||||
throw new ServiceException("就诊ID不能为空");
|
||||
}
|
||||
Encounter encounter = iEncounterService.getById(encounterId);
|
||||
if (encounter == null) {
|
||||
throw new ServiceException("未找到该住院登记记录");
|
||||
}
|
||||
// 仅"待入科"状态可修改
|
||||
if (!EncounterZyStatus.REGISTERED.getValue().equals(encounter.getStatusEnum())) {
|
||||
throw new ServiceException("患者已入科接收,无法修改登记信息");
|
||||
}
|
||||
|
||||
// 更新就诊信息
|
||||
encounter.setOrganizationId(inHospitalInfoDto.getInHospitalOrgId()); // 住院科室
|
||||
encounter.setPriorityEnum(inHospitalInfoDto.getPriorityEnum()); // 优先级(患者病情)
|
||||
encounter.setAdmitSourceCode(inHospitalInfoDto.getAdmitSourceCode()); // 入院类型
|
||||
encounter.setInWayCode(inHospitalInfoDto.getInWayCode()); // 入院方式
|
||||
encounter.setStartTime(inHospitalInfoDto.getStartTime()); // 入院日期
|
||||
encounter.setRegistrarId(SecurityUtils.getLoginUser().getPractitionerId()); // 登记员
|
||||
iEncounterService.saveOrUpdate(encounter);
|
||||
|
||||
// 更新病区信息
|
||||
EncounterLocation encounterLocation = iEncounterLocationService.getOne(
|
||||
new LambdaQueryWrapper<EncounterLocation>()
|
||||
.eq(EncounterLocation::getEncounterId, encounterId)
|
||||
.eq(EncounterLocation::getFormEnum, LocationForm.WARD.getValue()));
|
||||
if (inHospitalInfoDto.getWardLocationId() != null) {
|
||||
EncounterLocation encounterLocationReg = new EncounterLocation();
|
||||
if (encounterLocation != null) {
|
||||
encounterLocationReg.setId(encounterLocation.getId());
|
||||
}
|
||||
encounterLocationReg.setEncounterId(encounterId);
|
||||
encounterLocationReg.setLocationId(inHospitalInfoDto.getWardLocationId());
|
||||
encounterLocationReg.setFormEnum(LocationForm.WARD.getValue());
|
||||
iEncounterLocationService.saveOrUpdate(encounterLocationReg);
|
||||
}
|
||||
|
||||
// 更新费用性质(contractNo)对应的账户信息
|
||||
if (inHospitalInfoDto.getContractNo() != null) {
|
||||
boolean selfFunded = CommonConstants.BusinessName.DEFAULT_CONTRACT_NO.equals(inHospitalInfoDto.getContractNo());
|
||||
|
||||
// 查找自费账户(type_code='04')
|
||||
Account cashAccount = iAccountService.getOne(
|
||||
new LambdaQueryWrapper<Account>()
|
||||
.eq(Account::getEncounterId, encounterId)
|
||||
.eq(Account::getTypeCode, AccountType.PERSONAL_CASH_ACCOUNT.getCode()));
|
||||
|
||||
// 查找非自费账户
|
||||
Account contractAccount = iAccountService.getOne(
|
||||
new LambdaQueryWrapper<Account>()
|
||||
.eq(Account::getEncounterId, encounterId)
|
||||
.ne(Account::getTypeCode, AccountType.PERSONAL_CASH_ACCOUNT.getCode()));
|
||||
|
||||
if (selfFunded) {
|
||||
// 改为自费
|
||||
if (cashAccount != null) {
|
||||
cashAccount.setContractNo(CommonConstants.BusinessName.DEFAULT_CONTRACT_NO);
|
||||
cashAccount.setEncounterFlag(Whether.YES.getValue());
|
||||
iAccountService.saveOrUpdate(cashAccount);
|
||||
} else {
|
||||
// 不存在自费账户时,创建一个
|
||||
Account newCashAccount = new Account();
|
||||
newCashAccount.setTypeCode(AccountType.PERSONAL_CASH_ACCOUNT.getCode());
|
||||
newCashAccount.setPatientId(encounter.getPatientId());
|
||||
newCashAccount.setEncounterId(encounterId);
|
||||
newCashAccount.setContractNo(CommonConstants.BusinessName.DEFAULT_CONTRACT_NO);
|
||||
newCashAccount.setEncounterFlag(Whether.YES.getValue());
|
||||
newCashAccount.setBalanceAmount(BigDecimal.ZERO);
|
||||
iAccountService.save(newCashAccount);
|
||||
}
|
||||
// 删除非自费账户
|
||||
if (contractAccount != null) {
|
||||
iAccountService.removeById(contractAccount.getId());
|
||||
}
|
||||
} else {
|
||||
// 改为非自费
|
||||
if (cashAccount != null) {
|
||||
cashAccount.setEncounterFlag(Whether.NO.getValue());
|
||||
iAccountService.saveOrUpdate(cashAccount);
|
||||
} else {
|
||||
// 不存在自费账户时,创建一个
|
||||
Account newCashAccount = new Account();
|
||||
newCashAccount.setTypeCode(AccountType.PERSONAL_CASH_ACCOUNT.getCode());
|
||||
newCashAccount.setPatientId(encounter.getPatientId());
|
||||
newCashAccount.setEncounterId(encounterId);
|
||||
newCashAccount.setContractNo(CommonConstants.BusinessName.DEFAULT_CONTRACT_NO);
|
||||
newCashAccount.setEncounterFlag(Whether.NO.getValue());
|
||||
newCashAccount.setBalanceAmount(BigDecimal.ZERO);
|
||||
iAccountService.save(newCashAccount);
|
||||
}
|
||||
// 更新或创建非自费账户
|
||||
String typeCode = StringUtils.isNotEmpty(inHospitalInfoDto.getTypeCoce())
|
||||
? inHospitalInfoDto.getTypeCoce()
|
||||
: AccountType.PERSONAL_CASH_ACCOUNT.getCode();
|
||||
if (contractAccount != null) {
|
||||
contractAccount.setContractNo(inHospitalInfoDto.getContractNo());
|
||||
iAccountService.saveOrUpdate(contractAccount);
|
||||
} else {
|
||||
Account newAccount = new Account();
|
||||
newAccount.setTypeCode(typeCode);
|
||||
newAccount.setPatientId(encounter.getPatientId());
|
||||
newAccount.setEncounterId(encounterId);
|
||||
newAccount.setContractNo(inHospitalInfoDto.getContractNo());
|
||||
newAccount.setEncounterFlag(Whether.YES.getValue());
|
||||
iAccountService.save(newAccount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"住院登记"}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 作废住院登记
|
||||
*
|
||||
* @param encounterId 住院就诊id
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
public R<?> voidRegistration(Long encounterId) {
|
||||
if (encounterId == null) {
|
||||
throw new ServiceException("就诊ID不能为空");
|
||||
}
|
||||
Encounter encounter = iEncounterService.getById(encounterId);
|
||||
if (encounter == null) {
|
||||
throw new ServiceException("未找到该住院登记记录");
|
||||
}
|
||||
// 仅"待入科"状态可作废
|
||||
if (!EncounterZyStatus.REGISTERED.getValue().equals(encounter.getStatusEnum())) {
|
||||
throw new ServiceException("该患者已入科,请先通知护士站办理退科处理!");
|
||||
}
|
||||
|
||||
// 检查预交金余额
|
||||
Account cashAccount = iAccountService.getOne(
|
||||
new LambdaQueryWrapper<Account>()
|
||||
.eq(Account::getEncounterId, encounterId)
|
||||
.eq(Account::getTypeCode, AccountType.PERSONAL_CASH_ACCOUNT.getCode()));
|
||||
if (cashAccount != null && cashAccount.getBalanceAmount() != null
|
||||
&& cashAccount.getBalanceAmount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
throw new ServiceException("该患者存在未退清的预交金,请先前往预交金页面办理退款!");
|
||||
}
|
||||
|
||||
// 检查是否已产生计费
|
||||
long chargeCount = iChargeItemService.count(
|
||||
new LambdaQueryWrapper<ChargeItem>()
|
||||
.eq(ChargeItem::getEncounterId, encounterId));
|
||||
if (chargeCount > 0) {
|
||||
throw new ServiceException("该患者已产生计费记录,无法作废登记!");
|
||||
}
|
||||
|
||||
// 设置状态为已作废
|
||||
encounter.setStatusEnum(EncounterZyStatus.VOIDED.getValue());
|
||||
encounter.setRegistrarId(SecurityUtils.getLoginUser().getPractitionerId()); // 作废操作人
|
||||
iEncounterService.saveOrUpdate(encounter);
|
||||
|
||||
// 清理账户记录
|
||||
if (cashAccount != null) {
|
||||
iAccountService.removeById(cashAccount.getId());
|
||||
}
|
||||
// 清理非自费账户
|
||||
iAccountService.remove(
|
||||
new LambdaQueryWrapper<Account>()
|
||||
.eq(Account::getEncounterId, encounterId)
|
||||
.ne(Account::getTypeCode, AccountType.PERSONAL_CASH_ACCOUNT.getCode()));
|
||||
|
||||
return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"作废操作"}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理入院登记信息
|
||||
*
|
||||
|
||||
@@ -10,6 +10,8 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
@@ -53,6 +55,9 @@ public class InHospitalRegisterController {
|
||||
* @param registeredFlag 已登记标识,已登记传 1 ,待登记传 0
|
||||
* @param pageNo 当前页
|
||||
* @param pageSize 每页多少条
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param organizationId 入院科室ID
|
||||
* @param request 请求
|
||||
* @return 住院登记信息
|
||||
*/
|
||||
@@ -61,9 +66,13 @@ public class InHospitalRegisterController {
|
||||
@RequestParam(value = "searchKey", defaultValue = "") String searchKey,
|
||||
@RequestParam(value = "registeredFlag") String registeredFlag,
|
||||
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest request) {
|
||||
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(value = "startTime", required = false) Date startTime,
|
||||
@RequestParam(value = "endTime", required = false) Date endTime,
|
||||
@RequestParam(value = "organizationId", required = false) Long organizationId,
|
||||
HttpServletRequest request) {
|
||||
return R.ok(iInHospitalRegisterAppService.getRegisterInfo(inHospitalRegisterQueryDto, searchKey, registeredFlag,
|
||||
pageNo, pageSize, request));
|
||||
pageNo, pageSize, startTime, endTime, organizationId, request));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -142,4 +151,26 @@ public class InHospitalRegisterController {
|
||||
return R.ok(iInHospitalRegisterAppService.getWardList(orgId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改住院登记信息
|
||||
*
|
||||
* @param inHospitalInfoDto 登记dto
|
||||
* @return 结果
|
||||
*/
|
||||
@PutMapping(value = "/update-registration")
|
||||
public R<?> updateRegistration(@RequestBody InHospitalInfoDto inHospitalInfoDto) {
|
||||
return iInHospitalRegisterAppService.updateRegistration(inHospitalInfoDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 作废住院登记
|
||||
*
|
||||
* @param encounterId 住院就诊id
|
||||
* @return 结果
|
||||
*/
|
||||
@PutMapping(value = "/void-registration")
|
||||
public R<?> voidRegistration(@RequestParam(value = "encounterId") Long encounterId) {
|
||||
return iInHospitalRegisterAppService.voidRegistration(encounterId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -95,4 +95,29 @@ public class InHospitalRegisterQueryDto {
|
||||
private String admitSourceCode;
|
||||
private String admitSourceCode_dictText;
|
||||
|
||||
}
|
||||
/**
|
||||
* 住院状态
|
||||
*/
|
||||
private Integer statusEnum;
|
||||
|
||||
|
||||
/**
|
||||
* 开始时间(查询条件)
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date startTime;
|
||||
|
||||
/**
|
||||
* 结束时间(查询条件)
|
||||
*/
|
||||
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date endTime;
|
||||
|
||||
/**
|
||||
* 组织ID(查询条件)
|
||||
*/
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long organizationId;
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.healthlink.his.web.inhospitalcharge.dto.InHospitalRegisterQueryDto;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -27,12 +28,17 @@ public interface InHospitalRegisterAppMapper {
|
||||
* @param encounterStatus 登记状态
|
||||
* @param registeredFlag 已登记标识,已登记传 1 ,待登记传 0
|
||||
* @param formEnum 物理位置
|
||||
* @param startTime 开始时间
|
||||
* @param endTime 结束时间
|
||||
* @param organizationId 入院科室ID
|
||||
* @param queryWrapper 查询条件
|
||||
* @return 住院登记信息
|
||||
*/
|
||||
IPage<InHospitalRegisterQueryDto> getInHospitalRegisterInfo(@Param("page") Page<InHospitalRegisterQueryDto> page,
|
||||
@Param("encounterClass") Integer encounterClass, @Param("encounterStatus") Integer encounterStatus,
|
||||
@Param("registeredFlag") String registeredFlag, @Param("formEnum") Integer formEnum,
|
||||
@Param("startTime") Date startTime, @Param("endTime") Date endTime,
|
||||
@Param("organizationId") Long organizationId,
|
||||
@Param(Constants.WRAPPER) QueryWrapper<InHospitalRegisterQueryDto> queryWrapper);
|
||||
|
||||
/**
|
||||
|
||||
@@ -606,6 +606,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
* @return 结果
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public R<?> transferDepartment(Long encounterId) {
|
||||
if (encounterId == null) {
|
||||
return R.fail("转科失败,请选择有效的患者");
|
||||
@@ -663,6 +664,7 @@ public class ATDManageAppServiceImpl implements IATDManageAppService {
|
||||
// 更新住院信息
|
||||
encounter.setOrganizationId(orderProcess.getTargetOrganizationId())
|
||||
.setStatusEnum(EncounterZyStatus.REGISTERED.getValue());
|
||||
encounterService.saveOrUpdateEncounter(encounter);
|
||||
return R.ok("转科成功");
|
||||
}
|
||||
|
||||
|
||||
@@ -177,11 +177,17 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
||||
// 初始化查询参数
|
||||
String encounterIds = inpatientAdviceParam.getEncounterIds();
|
||||
inpatientAdviceParam.setEncounterIds(null);
|
||||
// Bug #715: 提取therapyEnum手动处理,避免自动条件排除therapy_enum为NULL的耗材医嘱
|
||||
Integer therapyEnum = inpatientAdviceParam.getTherapyEnum();
|
||||
inpatientAdviceParam.setTherapyEnum(null);
|
||||
Integer exeStatus = inpatientAdviceParam.getExeStatus();
|
||||
inpatientAdviceParam.setExeStatus(null);
|
||||
// 提取requestStatus手动处理,支持COMPLETED(3)和CHECK_VERIFIED(10)同时查询
|
||||
Integer requestStatus = inpatientAdviceParam.getRequestStatus();
|
||||
inpatientAdviceParam.setRequestStatus(null);
|
||||
// Bug #714: 提取deadline手动处理,UNION子查询列名为end_time
|
||||
String deadline = inpatientAdviceParam.getDeadline();
|
||||
inpatientAdviceParam.setDeadline(null);
|
||||
// 构建查询条件
|
||||
QueryWrapper<InpatientAdviceParam> queryWrapper
|
||||
= HisQueryUtils.buildQueryWrapper(inpatientAdviceParam, null, null, null);
|
||||
@@ -204,10 +210,25 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
||||
= Arrays.stream(encounterIds.split(CommonConstants.Common.COMMA)).map(Long::parseLong).toList();
|
||||
queryWrapper.in(CommonConstants.FieldName.EncounterId, encounterIdList);
|
||||
}
|
||||
// Bug #715: 手动拼接therapyEnum条件,耗材医嘱(DeviceRequest)无therapy_enum(NULL),需兼容
|
||||
if (therapyEnum != null) {
|
||||
queryWrapper.and(w -> w.eq("therapy_enum", therapyEnum).or().isNull("therapy_enum"));
|
||||
}
|
||||
// Bug #714: 手动拼接deadline条件,按医嘱截止时间筛选
|
||||
if (deadline != null && !deadline.isEmpty()) {
|
||||
try {
|
||||
LocalDateTime deadlineTime = LocalDateTime.parse(deadline,
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
queryWrapper.and(w -> w.le("end_time", deadlineTime).or().isNull("end_time"));
|
||||
} catch (DateTimeParseException e) {
|
||||
// 忽略无效的日期格式
|
||||
}
|
||||
}
|
||||
// 患者医嘱分页列表
|
||||
Page<InpatientAdviceDto> inpatientAdvicePage
|
||||
= adviceProcessAppMapper.selectInpatientAdvicePage(new Page<>(pageNo, pageSize), queryWrapper,
|
||||
CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_SERVICE_REQUEST,
|
||||
CommonConstants.TableName.WOR_DEVICE_REQUEST,
|
||||
RequestStatus.DRAFT.getValue(), EncounterActivityStatus.ACTIVE.getValue(), LocationForm.BED.getValue(),
|
||||
ParticipantType.ADMITTING_DOCTOR.getCode(), AccountType.PERSONAL_CASH_ACCOUNT.getCode(),
|
||||
ChargeItemStatus.BILLABLE.getValue(), ChargeItemStatus.BILLED.getValue(),
|
||||
@@ -230,6 +251,68 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
||||
if (e.getBirthDate() != null) {
|
||||
e.setAge(AgeCalculatorUtil.getAge(e.getBirthDate()));
|
||||
}
|
||||
|
||||
// ---------- Bug #595: 医嘱校对列表计算字段 ----------
|
||||
|
||||
// 单次剂量:剂量 + 单位
|
||||
if (e.getDose() != null) {
|
||||
String doseStr = e.getDose().stripTrailingZeros().toPlainString();
|
||||
String unitStr = e.getDoseUnitCode_dictText() != null ? e.getDoseUnitCode_dictText() : "";
|
||||
e.setSingleDose(doseStr + unitStr);
|
||||
}
|
||||
|
||||
// 总量:剂量 × 数量 + 单位(仅药品医嘱)
|
||||
if (e.getDose() != null && e.getQuantity() != null) {
|
||||
BigDecimal total = e.getDose().multiply(BigDecimal.valueOf(e.getQuantity()));
|
||||
String totalStr = total.stripTrailingZeros().toPlainString();
|
||||
String unitStr = e.getUnitCode_dictText() != null ? e.getUnitCode_dictText() : "";
|
||||
e.setTotalAmount(totalStr + unitStr);
|
||||
} else if (e.getQuantity() != null) {
|
||||
String unitStr = e.getUnitCode_dictText() != null ? e.getUnitCode_dictText() : "";
|
||||
e.setTotalAmount(e.getQuantity() + unitStr);
|
||||
}
|
||||
|
||||
// 频次/用法组合
|
||||
StringBuilder freqBuilder = new StringBuilder();
|
||||
if (e.getRateCode_dictText() != null && !e.getRateCode_dictText().isEmpty()) {
|
||||
freqBuilder.append(e.getRateCode_dictText());
|
||||
}
|
||||
if (e.getMethodCode_dictText() != null && !e.getMethodCode_dictText().isEmpty()) {
|
||||
if (freqBuilder.length() > 0) freqBuilder.append(" ");
|
||||
freqBuilder.append(e.getMethodCode_dictText());
|
||||
}
|
||||
e.setFrequencyUsage(freqBuilder.length() > 0 ? freqBuilder.toString() : null);
|
||||
|
||||
// 开嘱医生
|
||||
e.setOrderingDoctor(e.getRequesterId_dictText() != null
|
||||
? e.getRequesterId_dictText() : e.getAdmittingDoctorName());
|
||||
|
||||
// 皮试状态 + 高亮
|
||||
if (e.getSkinTestFlag() != null && e.getSkinTestFlag() == 1) {
|
||||
e.setSkinTestStatus("需皮试");
|
||||
e.setSkinTestHighlight(true);
|
||||
} else if (e.getSkinTestFlag() != null && e.getSkinTestFlag() == 2) {
|
||||
e.setSkinTestStatus("皮试通过");
|
||||
e.setSkinTestHighlight(false);
|
||||
} else {
|
||||
e.setSkinTestStatus("无需");
|
||||
e.setSkinTestHighlight(false);
|
||||
}
|
||||
|
||||
// 注射药品标记
|
||||
e.setIsInjection(e.getInjectFlag() != null && e.getInjectFlag() == 1);
|
||||
|
||||
// 停嘱医生
|
||||
e.setStopperName(e.getStopperName());
|
||||
|
||||
// 停嘱时间
|
||||
e.setStopTime(e.getEndTime());
|
||||
|
||||
// 医嘱号
|
||||
e.setOrderNo(e.getRequestId() != null ? e.getRequestId().toString() : null);
|
||||
|
||||
// 诊断(行级)
|
||||
e.setDiagnosis(e.getConditionNames());
|
||||
});
|
||||
|
||||
// 获取医嘱列表
|
||||
@@ -317,14 +400,17 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
||||
*/
|
||||
@Override
|
||||
public R<?> adviceVerify(List<PerformInfoDto> performInfoList) {
|
||||
// 分别创建两个列表来存储不同类型的请求
|
||||
// 分别创建列表来存储不同类型的请求
|
||||
List<PerformInfoDto> serviceRequestList = new ArrayList<>();
|
||||
List<PerformInfoDto> medRequestList = new ArrayList<>();
|
||||
List<PerformInfoDto> deviceRequestList = new ArrayList<>();
|
||||
for (PerformInfoDto item : performInfoList) {
|
||||
if (CommonConstants.TableName.WOR_SERVICE_REQUEST.equals(item.getRequestTable())) {
|
||||
serviceRequestList.add(item);
|
||||
} else if (CommonConstants.TableName.MED_MEDICATION_REQUEST.equals(item.getRequestTable())) {
|
||||
medRequestList.add(item);
|
||||
} else if (CommonConstants.TableName.WOR_DEVICE_REQUEST.equals(item.getRequestTable())) {
|
||||
deviceRequestList.add(item);
|
||||
}
|
||||
}
|
||||
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
||||
@@ -363,6 +449,11 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
||||
medicationRequestService.updateCompletedStatusBatch(
|
||||
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
|
||||
}
|
||||
if (!deviceRequestList.isEmpty()) {
|
||||
// 更新耗材请求状态已完成
|
||||
deviceRequestService.updateCompletedStatusBatch(
|
||||
deviceRequestList.stream().map(PerformInfoDto::getRequestId).toList());
|
||||
}
|
||||
return R.ok(null, "校对成功");
|
||||
}
|
||||
|
||||
@@ -374,14 +465,17 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
||||
*/
|
||||
@Override
|
||||
public R<?> adviceReject(List<PerformInfoDto> performInfoList) {
|
||||
// 分别创建两个列表来存储不同类型的请求
|
||||
// 分别创建列表来存储不同类型的请求
|
||||
List<PerformInfoDto> serviceRequestList = new ArrayList<>();
|
||||
List<PerformInfoDto> medRequestList = new ArrayList<>();
|
||||
List<PerformInfoDto> deviceRequestList = new ArrayList<>();
|
||||
for (PerformInfoDto item : performInfoList) {
|
||||
if (CommonConstants.TableName.WOR_SERVICE_REQUEST.equals(item.getRequestTable())) {
|
||||
serviceRequestList.add(item);
|
||||
} else if (CommonConstants.TableName.MED_MEDICATION_REQUEST.equals(item.getRequestTable())) {
|
||||
medRequestList.add(item);
|
||||
} else if (CommonConstants.TableName.WOR_DEVICE_REQUEST.equals(item.getRequestTable())) {
|
||||
deviceRequestList.add(item);
|
||||
}
|
||||
}
|
||||
// 校验医嘱是否已执行,已执行的医嘱需要先取消执行后才能退回
|
||||
@@ -431,6 +525,11 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
||||
medicationRequestService.updateDraftStatusBatch(
|
||||
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason);
|
||||
}
|
||||
if (!deviceRequestList.isEmpty()) {
|
||||
// 更新耗材请求状态待发送
|
||||
deviceRequestService.updateDraftStatusBatch(
|
||||
deviceRequestList.stream().map(PerformInfoDto::getRequestId).toList());
|
||||
}
|
||||
return R.ok(null, "退回成功");
|
||||
}
|
||||
|
||||
|
||||
@@ -259,4 +259,40 @@ public class InpatientAdviceDto {
|
||||
/** 发药状态 */
|
||||
private Integer dispenseStatus;
|
||||
private String dispenseStatus_enumText;
|
||||
|
||||
// ========== Bug #595 计算展示字段 ==========
|
||||
|
||||
/** 单次剂量(格式化:剂量+单位) */
|
||||
private String singleDose;
|
||||
|
||||
/** 总量(格式化:剂量×数量+单位) */
|
||||
private String totalAmount;
|
||||
|
||||
/** 频次/用法组合(如:tid 静滴) */
|
||||
private String frequencyUsage;
|
||||
|
||||
/** 开嘱医生 */
|
||||
private String orderingDoctor;
|
||||
|
||||
/** 皮试状态文本(需皮试/皮试通过/无需) */
|
||||
private String skinTestStatus;
|
||||
|
||||
/** 皮试高亮标记(需皮试时为true) */
|
||||
private Boolean skinTestHighlight;
|
||||
|
||||
/** 是否注射药品 */
|
||||
private Boolean isInjection;
|
||||
|
||||
/** 停嘱医生 */
|
||||
private String stopperName;
|
||||
|
||||
/** 停嘱时间 */
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date stopTime;
|
||||
|
||||
/** 医嘱号 */
|
||||
private String orderNo;
|
||||
|
||||
/** 诊断(行级展示) */
|
||||
private String diagnosis;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,8 @@ public interface AdviceProcessAppMapper {
|
||||
Page<InpatientAdviceDto> selectInpatientAdvicePage(@Param("page") Page<InpatientAdviceDto> page,
|
||||
@Param(Constants.WRAPPER) QueryWrapper<InpatientAdviceParam> queryWrapper,
|
||||
@Param("medMedicationRequest") String medMedicationRequest,
|
||||
@Param("worServiceRequest") String worServiceRequest, @Param("draft") Integer draft,
|
||||
@Param("worServiceRequest") String worServiceRequest,
|
||||
@Param("worDeviceRequest") String worDeviceRequest, @Param("draft") Integer draft,
|
||||
@Param("active") Integer active, @Param("bed") Integer bed, @Param("admittingDoctor") String admittingDoctor,
|
||||
@Param("personalCashAccount") String personalCashAccount, @Param("billable") Integer billable,
|
||||
@Param("billed") Integer billed, @Param("refunded") Integer refunded, @Param("imp") Integer imp,
|
||||
|
||||
@@ -36,6 +36,8 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -310,13 +312,73 @@ public class PatientInformationServiceImpl implements IPatientInformationService
|
||||
patient.setBloodAbo(patientInfoDto.getBloodAbo()); // 血型ABO
|
||||
patient.setBloodRh(patientInfoDto.getBloodRh()); // 血型RH
|
||||
patient.setMaritalStatusEnum(patientInfoDto.getMaritalStatusEnum()); // 婚姻状态
|
||||
patient.setDeceasedDate(patientInfoDto.getDeceasedDate()); // 死亡时间
|
||||
// 死亡时间:支持 yyyy-MM-dd HH:mm:ss 和 yyyy/MM/dd HH:mm:ss 格式
|
||||
if (patientInfoDto.getDeceasedDate() != null && !patientInfoDto.getDeceasedDate().isEmpty()) {
|
||||
String dateStr = patientInfoDto.getDeceasedDate();
|
||||
String[] patterns = {"yyyy-MM-dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss", "yyyy/M/d HH:mm:ss"};
|
||||
Date parsedDate = null;
|
||||
for (String pat : patterns) {
|
||||
try { parsedDate = new SimpleDateFormat(pat).parse(dateStr); break; } catch (Exception ignored) {}
|
||||
}
|
||||
patient.setDeceasedDate(parsedDate);
|
||||
} else {
|
||||
patient.setDeceasedDate(null);
|
||||
}
|
||||
patient.setNationalityCode(patientInfoDto.getNationalityCode());// 民族
|
||||
patient.setActiveFlag(patientInfoDto.getActiveFlag());// 活动标识
|
||||
patient.setCountryCode(patientInfoDto.getCountryCode());// 国家编码
|
||||
patient.setPostalCode(patientInfoDto.getPostalCode());// 邮政编码
|
||||
patient.setHukouAddress(patientInfoDto.getHukouAddress());// 户籍地址
|
||||
patient.setGuardianName(patientInfoDto.getGuardianName());// 监护人姓名
|
||||
patient.setGuardianRelation(patientInfoDto.getGuardianRelation());// 监护人关系
|
||||
patient.setGuardianPhone(patientInfoDto.getGuardianPhone());// 监护人电话
|
||||
patient.setGuardianIdType(patientInfoDto.getGuardianIdType());// 监护人证件类型
|
||||
patient.setGuardianIdNo(patientInfoDto.getGuardianIdNo());// 监护人证件号码
|
||||
patient.setGuardianAddress(patientInfoDto.getGuardianAddress());// 监护人地址
|
||||
patient.setPatientDerived(patientInfoDto.getPatientDerived());// 患者来源
|
||||
patient.setEducationLevel(patientInfoDto.getEducationLevel());// 文化程度
|
||||
patient.setCompanyAddress(patientInfoDto.getCompanyAddress());// 单位地址
|
||||
|
||||
if (patientInfoDto.getId() != null) {
|
||||
// 更新操作
|
||||
patientService.updateById(patient);
|
||||
// 更新操作 - 使用 LambdaUpdateWrapper 显式设置所有字段,确保 null 值也能正确更新
|
||||
LambdaUpdateWrapper<Patient> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(Patient::getId, patient.getId())
|
||||
.set(Patient::getName, patient.getName())
|
||||
.set(Patient::getPyStr, patient.getPyStr())
|
||||
.set(Patient::getWbStr, patient.getWbStr())
|
||||
.set(Patient::getIdCard, patient.getIdCard())
|
||||
.set(Patient::getBirthDate, patient.getBirthDate())
|
||||
.set(Patient::getGenderEnum, patient.getGenderEnum())
|
||||
.set(Patient::getPhone, patient.getPhone())
|
||||
.set(Patient::getPrfsEnum, patient.getPrfsEnum())
|
||||
.set(Patient::getWorkCompany, patient.getWorkCompany())
|
||||
.set(Patient::getLinkName, patient.getLinkName())
|
||||
.set(Patient::getLinkRelationCode, patient.getLinkRelationCode())
|
||||
.set(Patient::getLinkTelcom, patient.getLinkTelcom())
|
||||
.set(Patient::getAddress, patient.getAddress())
|
||||
.set(Patient::getAddressProvince, patient.getAddressProvince())
|
||||
.set(Patient::getAddressCity, patient.getAddressCity())
|
||||
.set(Patient::getAddressDistrict, patient.getAddressDistrict())
|
||||
.set(Patient::getAddressStreet, patient.getAddressStreet())
|
||||
.set(Patient::getBloodAbo, patient.getBloodAbo())
|
||||
.set(Patient::getBloodRh, patient.getBloodRh())
|
||||
.set(Patient::getMaritalStatusEnum, patient.getMaritalStatusEnum())
|
||||
.set(Patient::getDeceasedDate, patient.getDeceasedDate())
|
||||
.set(Patient::getNationalityCode, patient.getNationalityCode())
|
||||
.set(Patient::getActiveFlag, patient.getActiveFlag())
|
||||
.set(Patient::getCountryCode, patient.getCountryCode())
|
||||
.set(Patient::getPostalCode, patient.getPostalCode())
|
||||
.set(Patient::getHukouAddress, patient.getHukouAddress())
|
||||
.set(Patient::getGuardianName, patient.getGuardianName())
|
||||
.set(Patient::getGuardianRelation, patient.getGuardianRelation())
|
||||
.set(Patient::getGuardianPhone, patient.getGuardianPhone())
|
||||
.set(Patient::getGuardianIdType, patient.getGuardianIdType())
|
||||
.set(Patient::getGuardianIdNo, patient.getGuardianIdNo())
|
||||
.set(Patient::getGuardianAddress, patient.getGuardianAddress())
|
||||
.set(Patient::getPatientDerived, patient.getPatientDerived())
|
||||
.set(Patient::getEducationLevel, patient.getEducationLevel())
|
||||
.set(Patient::getCompanyAddress, patient.getCompanyAddress());
|
||||
patientService.update(updateWrapper);
|
||||
} else {
|
||||
// 新增操作
|
||||
patientService.save(patient);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.healthlink.his.web.patientmanage.dto;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 支持多种日期格式的反序列化器
|
||||
* 兼容 yyyy-MM-dd HH:mm:ss 和 yyyy/MM/dd HH:mm:ss 等格式
|
||||
*/
|
||||
public class FlexibleDateDeserializer extends JsonDeserializer<Date> {
|
||||
|
||||
private static final String[] DATE_FORMATS = {
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
"yyyy/MM/dd HH:mm:ss",
|
||||
"yyyy/M/d HH:mm:ss",
|
||||
"yyyy-MM-dd'T'HH:mm:ss",
|
||||
"yyyy-MM-dd'T'HH:mm:ss.SSS",
|
||||
"yyyy-MM-dd",
|
||||
"yyyy/MM/dd"
|
||||
};
|
||||
|
||||
@Override
|
||||
public Date deserialize(JsonParser p, DeserializationContext context) throws IOException {
|
||||
String dateStr = p.getValueAsString();
|
||||
if (dateStr == null || dateStr.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (String pattern : DATE_FORMATS) {
|
||||
try {
|
||||
return new SimpleDateFormat(pattern).parse(dateStr);
|
||||
} catch (ParseException ignored) {
|
||||
}
|
||||
}
|
||||
throw new IOException("无法解析日期: " + dateStr + ",支持格式: yyyy-MM-dd HH:mm:ss 或 yyyy/MM/dd HH:mm:ss");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.healthlink.his.web.patientmanage.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.healthlink.his.common.annotation.Dict;
|
||||
@@ -144,8 +145,7 @@ public class PatientBaseInfoDto {
|
||||
/**
|
||||
* 死亡时间
|
||||
*/
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date deceasedDate;
|
||||
private String deceasedDate;
|
||||
|
||||
/**
|
||||
* 病人证件信息集合
|
||||
@@ -168,4 +168,65 @@ public class PatientBaseInfoDto {
|
||||
*/
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
* 邮政编码
|
||||
*/
|
||||
private String postalCode;
|
||||
|
||||
/**
|
||||
* 户籍地址
|
||||
*/
|
||||
private String hukouAddress;
|
||||
|
||||
/**
|
||||
* 监护人姓名
|
||||
*/
|
||||
private String guardianName;
|
||||
|
||||
/**
|
||||
* 监护人关系
|
||||
*/
|
||||
private Integer guardianRelation;
|
||||
private String guardianRelation_enumText;
|
||||
|
||||
/**
|
||||
* 监护人电话
|
||||
*/
|
||||
private String guardianPhone;
|
||||
|
||||
/**
|
||||
* 监护人证件类型
|
||||
*/
|
||||
private String guardianIdType;
|
||||
|
||||
/**
|
||||
* 监护人证件号码
|
||||
*/
|
||||
private String guardianIdNo;
|
||||
|
||||
/**
|
||||
* 监护人地址
|
||||
*/
|
||||
private String guardianAddress;
|
||||
|
||||
/**
|
||||
* 患者来源
|
||||
*/
|
||||
private String patientDerived;
|
||||
|
||||
/**
|
||||
* 文化程度
|
||||
*/
|
||||
private String educationLevel;
|
||||
|
||||
/**
|
||||
* 单位地址
|
||||
*/
|
||||
private String companyAddress;
|
||||
|
||||
/**
|
||||
* 国家编码
|
||||
*/
|
||||
private String countryCode;
|
||||
}
|
||||
|
||||
@@ -155,6 +155,10 @@ public class WesternMedicineDispenseAppServiceImpl implements IWesternMedicineDi
|
||||
|
||||
// 发药状态
|
||||
List<DispenseStatusOption> dispenseStatusOptions = new ArrayList<>();
|
||||
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.DRAFT.getValue(),
|
||||
DispenseStatus.DRAFT.getInfo()));
|
||||
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.SUBMITTED.getValue(),
|
||||
DispenseStatus.SUBMITTED.getInfo()));
|
||||
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.IN_PROGRESS.getValue(),
|
||||
DispenseStatus.IN_PROGRESS.getInfo()));
|
||||
dispenseStatusOptions.add(new DispenseStatusOption(DispenseStatus.COMPLETED.getValue(),
|
||||
@@ -193,7 +197,8 @@ public class WesternMedicineDispenseAppServiceImpl implements IWesternMedicineDi
|
||||
= westernMedicineDispenseMapper.selectEncounterInfoListPage(new Page<>(pageNo, pageSize), queryWrapper,
|
||||
statusEnum, DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.COMPLETED.getValue(),
|
||||
DispenseStatus.PREPARATION.getValue(), DispenseStatus.PREPARED.getValue(),
|
||||
DispenseStatus.SUMMARIZED.getValue(), DispenseStatus.SUBMITTED.getValue());
|
||||
DispenseStatus.SUMMARIZED.getValue(), DispenseStatus.SUBMITTED.getValue(),
|
||||
DispenseStatus.DRAFT.getValue());
|
||||
encounterInfoPage.getRecords().forEach(encounterInfo -> {
|
||||
// 性别
|
||||
encounterInfo.setGenderEnum_enumText(
|
||||
@@ -232,7 +237,7 @@ public class WesternMedicineDispenseAppServiceImpl implements IWesternMedicineDi
|
||||
DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.COMPLETED.getValue(),
|
||||
DispenseStatus.PREPARATION.getValue(), DispenseStatus.PREPARED.getValue(), dispenseStatus,
|
||||
PublicationStatus.ACTIVE.getValue(), DispenseStatus.SUMMARIZED.getValue(),
|
||||
DispenseStatus.SUBMITTED.getValue());
|
||||
DispenseStatus.SUBMITTED.getValue(), DispenseStatus.DRAFT.getValue());
|
||||
medicineDispenseOrderPage.getRecords().forEach(medicineDispenseOrder -> {
|
||||
// 发药状态
|
||||
medicineDispenseOrder.setStatusEnum_enumText(
|
||||
|
||||
@@ -25,6 +25,7 @@ public interface WesternMedicineDispenseMapper {
|
||||
* @param page 分页
|
||||
* @param queryWrapper 查询条件
|
||||
* @param statusEnum 发药状态
|
||||
* @param draft 发药状态:草稿
|
||||
* @param inProgress 发药状态:待发药
|
||||
* @param completed 发药状态:已发药
|
||||
* @param preparation 发药状态:待配药
|
||||
@@ -36,7 +37,8 @@ public interface WesternMedicineDispenseMapper {
|
||||
@Param("statusEnum") Integer statusEnum, @Param("inProgress") Integer inProgress,
|
||||
@Param("completed") Integer completed, @Param("preparation") Integer preparation,
|
||||
@Param("prepared") Integer prepared, @Param("summarized") Integer summarized,
|
||||
@Param("submitted") Integer submitted);
|
||||
@Param("submitted") Integer submitted,
|
||||
@Param("draft") Integer draft);
|
||||
|
||||
/**
|
||||
* 发药单查询
|
||||
@@ -48,6 +50,7 @@ public interface WesternMedicineDispenseMapper {
|
||||
* @param preparation 发药状态:待配药
|
||||
* @param prepared 发药状态:已配药
|
||||
* @param dispenseStatus 发药状态
|
||||
* @param draft 发药状态:草稿
|
||||
* @param active 库房状态:启用
|
||||
* @return 发耗材单列表
|
||||
*/
|
||||
@@ -56,7 +59,8 @@ public interface WesternMedicineDispenseMapper {
|
||||
@Param("inProgress") Integer inProgress, @Param("completed") Integer completed,
|
||||
@Param("preparation") Integer preparation, @Param("prepared") Integer prepared,
|
||||
@Param("dispenseStatus") Integer dispenseStatus, @Param("active") Integer active,
|
||||
@Param("summarized") Integer summarized, @Param("submitted") Integer submitted);
|
||||
@Param("summarized") Integer summarized, @Param("submitted") Integer submitted,
|
||||
@Param("draft") Integer draft);
|
||||
|
||||
/**
|
||||
* 获取配药人下拉选列表
|
||||
|
||||
@@ -4,6 +4,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.core.common.core.domain.R;
|
||||
import com.healthlink.his.reconstruction.domain.*;
|
||||
import com.healthlink.his.reconstruction.service.*;
|
||||
import com.core.system.service.ISysUserService;
|
||||
import com.core.system.service.ISysRoleService;
|
||||
import com.core.common.core.domain.entity.SysRole;
|
||||
import com.core.common.core.domain.entity.SysUser;
|
||||
import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;import org.springframework.web.bind.annotation.*;
|
||||
@@ -13,6 +17,8 @@ public class Reconstruction3DController {
|
||||
private final IReconstructionTaskService taskService;
|
||||
private final IReconstructionResultService resultService;
|
||||
private final IReconstructionReportService reportService;
|
||||
private final ISysUserService userService;
|
||||
private final ISysRoleService roleService;
|
||||
|
||||
// ==================== 重建任务 ====================
|
||||
@GetMapping("/task/page")
|
||||
@@ -100,4 +106,32 @@ public class Reconstruction3DController {
|
||||
stats.put("totalReports", reportService.count());
|
||||
return R.ok(stats);
|
||||
}
|
||||
|
||||
// ==================== 医生列表 ====================
|
||||
@GetMapping("/doctors")
|
||||
public R<?> getDoctors() {
|
||||
SysUser query = new SysUser();
|
||||
query.setStatus("0");
|
||||
query.setDelFlag("0");
|
||||
List<SysUser> allUsers = userService.selectUserList(query);
|
||||
// For each user, check if they have role 200 (doctor)
|
||||
List<Map<String, Object>> doctors = new ArrayList<>();
|
||||
for (SysUser user : allUsers) {
|
||||
List<SysRole> roles = roleService.selectRolesByUserId(user.getUserId());
|
||||
if (roles != null) {
|
||||
for (SysRole role : roles) {
|
||||
if (role.getRoleId() != null && role.getRoleId() == 200L) {
|
||||
Map<String, Object> doc = new HashMap<>();
|
||||
doc.put("userId", user.getUserId());
|
||||
doc.put("userName", user.getUserName());
|
||||
doc.put("nickName", user.getNickName());
|
||||
doctors.add(doc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return R.ok(doctors);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.core.common.core.domain.R;
|
||||
import com.core.common.utils.AssignSeqUtil;
|
||||
import com.core.common.utils.MessageUtils;
|
||||
import com.core.common.utils.SecurityUtils;
|
||||
import com.core.common.utils.StringUtils;
|
||||
import com.healthlink.his.common.constant.CommonConstants;
|
||||
import com.healthlink.his.common.constant.PromptMsgConstant;
|
||||
import com.healthlink.his.common.enums.*;
|
||||
@@ -18,7 +19,13 @@ import com.healthlink.his.web.regdoctorstation.dto.*;
|
||||
import com.healthlink.his.web.regdoctorstation.mapper.SpecialAdviceAppMapper;
|
||||
import com.healthlink.his.workflow.domain.ServiceRequest;
|
||||
import com.healthlink.his.workflow.service.IActivityDefinitionService;
|
||||
import com.healthlink.his.administration.domain.Encounter;
|
||||
import com.healthlink.his.administration.domain.Organization;
|
||||
import com.healthlink.his.administration.service.IEncounterService;
|
||||
import com.healthlink.his.administration.service.IOrganizationService;
|
||||
import com.healthlink.his.workflow.service.IServiceRequestService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -56,6 +63,12 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
|
||||
@Resource
|
||||
IOrderProcessService iOrderProcessService;
|
||||
|
||||
@Resource
|
||||
IEncounterService iEncounterService;
|
||||
|
||||
@Resource
|
||||
IOrganizationService iOrganizationService;
|
||||
|
||||
/**
|
||||
* 查询护理医嘱信息
|
||||
*
|
||||
@@ -351,6 +364,29 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
|
||||
AdviceBaseDto activityAdviceBaseDto = iDoctorStationAdviceAppService
|
||||
.getAdviceBaseInfo(adviceBaseDto, null, null, null, null, 1, 1, null, List.of(3), null, null, null)
|
||||
.getRecords().get(0);
|
||||
// 查询患者当前科室(从就诊记录获取)
|
||||
Encounter encounter = iEncounterService.getById(encounterId);
|
||||
Long currentOrgId = encounter != null ? encounter.getOrganizationId() : null;
|
||||
if (currentOrgId == null) {
|
||||
log.warn("转科医嘱:就诊记录 organizationId 为空, encounterId={}, 回退到医嘱定义默认科室", encounterId);
|
||||
currentOrgId = activityAdviceBaseDto.getPositionId();
|
||||
}
|
||||
|
||||
// 查询转入科室名称,用于医嘱名称拼接
|
||||
String targetOrgName = "";
|
||||
Long targetOrgId = transferOrganizationParam.getTargetOrganizationId();
|
||||
if (targetOrgId != null) {
|
||||
Organization targetOrg = iOrganizationService.getById(targetOrgId);
|
||||
if (targetOrg != null && StringUtils.isNotEmpty(targetOrg.getName())) {
|
||||
targetOrgName = targetOrg.getName();
|
||||
} else {
|
||||
log.warn("转科医嘱:查询转入科室失败, targetOrgId={}, 尝试通过 orgId 直接查", targetOrgId);
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(targetOrgName) && targetOrgId != null) {
|
||||
log.warn("转科医嘱:转入科室名称为空, targetOrgId={}, contentJson 中 adviceName 将缺少科室名", targetOrgId);
|
||||
}
|
||||
|
||||
// 保存转科医嘱请求
|
||||
ServiceRequest serviceRequest = new ServiceRequest();
|
||||
serviceRequest.setStatusEnum(RequestStatus.DRAFT.getValue());// 请求状态
|
||||
@@ -366,9 +402,18 @@ public class SpecialAdviceAppServiceImpl implements ISpecialAdviceAppService {
|
||||
serviceRequest.setPatientId(patientId); // 患者
|
||||
serviceRequest.setRequesterId(practitionerId); // 开方医生
|
||||
serviceRequest.setEncounterId(encounterId); // 就诊id
|
||||
serviceRequest.setOrgId(activityAdviceBaseDto.getPositionId()); // 执行科室
|
||||
serviceRequest.setOrgId(currentOrgId); // 执行科室(患者当前科室)
|
||||
serviceRequest.setConditionId(conditionId); // 诊断id
|
||||
serviceRequest.setEncounterDiagnosisId(encounterDiagnosisId); // 就诊诊断id
|
||||
// 设置医嘱名称:转科-转入科室名称
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
ObjectNode contentNode = objectMapper.createObjectNode();
|
||||
contentNode.put("adviceName", "转科" + (StringUtils.isNotEmpty(targetOrgName) ? "-" + targetOrgName : ""));
|
||||
serviceRequest.setContentJson(objectMapper.writeValueAsString(contentNode));
|
||||
} catch (Exception e) {
|
||||
log.warn("设置转科医嘱名称失败", e);
|
||||
}
|
||||
iServiceRequestService.save(serviceRequest);
|
||||
|
||||
// 保存转科医嘱请求的过程数据
|
||||
|
||||
@@ -16,7 +16,7 @@ public class RequestFormDetailQueryDto {
|
||||
/**
|
||||
* 诊疗活动定义ID(wor_service_request.activity_id,与开立检验时项目字典的 id / adviceDefinitionId 一致,用于编辑回显)
|
||||
*/
|
||||
private Long activityId;
|
||||
private Long adviceDefinitionId;
|
||||
|
||||
/** 医嘱名称 */
|
||||
private String adviceName;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
-- Bug #705: 患者管理修改后字段回显丢失修复
|
||||
-- 添加邮政编码、户籍地址、监护人信息、患者来源等缺失字段到adm_patient表
|
||||
|
||||
-- 邮政编码
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS postal_code VARCHAR(10);
|
||||
|
||||
-- 户籍地址
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS hukou_address VARCHAR(500);
|
||||
|
||||
-- 监护人信息
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS guardian_name VARCHAR(50);
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS guardian_relation INTEGER;
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS guardian_phone VARCHAR(20);
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS guardian_id_type VARCHAR(10);
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS guardian_id_no VARCHAR(30);
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS guardian_address VARCHAR(500);
|
||||
|
||||
-- 患者来源
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS patient_derived VARCHAR(50);
|
||||
|
||||
-- 文化程度
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS education_level VARCHAR(20);
|
||||
|
||||
-- 单位地址
|
||||
ALTER TABLE adm_patient ADD COLUMN IF NOT EXISTS company_address VARCHAR(500);
|
||||
@@ -0,0 +1,79 @@
|
||||
-- V40: 修复EMR模块数据库表结构问题
|
||||
-- 1. emr_archive_record表:添加缺失的审计字段,修复NOT NULL约束
|
||||
-- 2. emr_search_index表:修复NOT NULL约束
|
||||
-- 3. emr_revision表:添加缺失的审计字段
|
||||
|
||||
-- ==========================================
|
||||
-- 1. emr_archive_record 表修复
|
||||
-- ==========================================
|
||||
|
||||
-- 添加缺失的审计字段(如果不存在)
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_archive_record' AND column_name = 'create_by') THEN
|
||||
ALTER TABLE emr_archive_record ADD COLUMN create_by character varying;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_archive_record' AND column_name = 'update_by') THEN
|
||||
ALTER TABLE emr_archive_record ADD COLUMN update_by character varying;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_archive_record' AND column_name = 'update_time') THEN
|
||||
ALTER TABLE emr_archive_record ADD COLUMN update_time timestamp without time zone;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 修复NOT NULL约束
|
||||
ALTER TABLE emr_archive_record ALTER COLUMN emr_id DROP NOT NULL;
|
||||
ALTER TABLE emr_archive_record ALTER COLUMN patient_id DROP NOT NULL;
|
||||
ALTER TABLE emr_archive_record ALTER COLUMN archive_type DROP NOT NULL;
|
||||
|
||||
-- ==========================================
|
||||
-- 2. emr_search_index 表修复
|
||||
-- ==========================================
|
||||
|
||||
-- 修复NOT NULL约束
|
||||
ALTER TABLE emr_search_index ALTER COLUMN emr_id DROP NOT NULL;
|
||||
ALTER TABLE emr_search_index ALTER COLUMN encounter_id DROP NOT NULL;
|
||||
ALTER TABLE emr_search_index ALTER COLUMN patient_id DROP NOT NULL;
|
||||
|
||||
-- ==========================================
|
||||
-- 3. emr_revision 表修复
|
||||
-- ==========================================
|
||||
|
||||
-- 添加缺失的审计字段
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_revision' AND column_name = 'create_by') THEN
|
||||
ALTER TABLE emr_revision ADD COLUMN create_by character varying;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_revision' AND column_name = 'tenant_id') THEN
|
||||
ALTER TABLE emr_revision ADD COLUMN tenant_id bigint;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_revision' AND column_name = 'update_by') THEN
|
||||
ALTER TABLE emr_revision ADD COLUMN update_by character varying;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_revision' AND column_name = 'update_time') THEN
|
||||
ALTER TABLE emr_revision ADD COLUMN update_time timestamp without time zone;
|
||||
END IF;
|
||||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'emr_revision' AND column_name = 'delete_flag') THEN
|
||||
ALTER TABLE emr_revision ADD COLUMN delete_flag character varying;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- ==========================================
|
||||
-- 4. 添加索引以优化查询性能
|
||||
-- ==========================================
|
||||
|
||||
-- emr_archive_record 索引
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_archive_patient_name ON emr_archive_record(patient_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_archive_status ON emr_archive_record(archive_status);
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_archive_encounter ON emr_archive_record(encounter_id);
|
||||
|
||||
-- emr_search_index 索引
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_search_patient ON emr_search_index(patient_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_search_type ON emr_search_index(emr_type);
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_search_doctor ON emr_search_index(doctor_name);
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_search_dept ON emr_search_index(department_name);
|
||||
|
||||
-- emr_revision 索引
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_revision_emr ON emr_revision(emr_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_emr_revision_operator ON emr_revision(operator_name);
|
||||
@@ -0,0 +1,9 @@
|
||||
-- Bug #735: 新医嘱签发后"停嘱医生"字段错误生成数据
|
||||
-- 原因:stopper_name 映射到 update_by 字段,签发时 MyBatis-Plus 自动填充导致错误赋值
|
||||
-- 修复:添加专用 stopper_id 字段,仅在停嘱操作时设置
|
||||
|
||||
-- 药品请求表添加停嘱医生ID字段
|
||||
ALTER TABLE med_medication_request ADD COLUMN IF NOT EXISTS stopper_id BIGINT;
|
||||
|
||||
-- 服务请求表添加停嘱医生ID字段
|
||||
ALTER TABLE wor_service_request ADD COLUMN IF NOT EXISTS stopper_id BIGINT;
|
||||
@@ -217,6 +217,11 @@
|
||||
WHERE T1.delete_flag = '0'
|
||||
AND T1.class_enum = #{classEnum}
|
||||
AND T10.context_enum = #{register}
|
||||
AND (#{registerTimeSTime} IS NULL OR T1.create_time >= CAST(#{registerTimeSTime} AS TIMESTAMP))
|
||||
AND (#{registerTimeETime} IS NULL OR T1.create_time <= CAST(#{registerTimeETime} AS TIMESTAMP))
|
||||
AND (#{statusFilter} IS NULL
|
||||
OR (#{statusFilter} >= 0 AND T1.status_enum = #{statusFilter})
|
||||
OR (#{statusFilter} = -1 AND T1.status_enum != 6))
|
||||
) AS T9
|
||||
${ew.customSqlSegment}
|
||||
ORDER BY T9.register_time DESC
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
ihri.ward_name,
|
||||
ihri.contract_no,
|
||||
ihri.bus_no,
|
||||
ihri.admit_source_code
|
||||
ihri.admit_source_code,
|
||||
ihri.status_enum,
|
||||
ihri.id_card,
|
||||
ihri.organization_name
|
||||
from (SELECT ae.tenant_id,
|
||||
ae.ID AS encounter_id,
|
||||
ae.amb_encounter_id AS amb_encounter_id,
|
||||
@@ -32,8 +35,13 @@
|
||||
al.NAME AS ward_name,
|
||||
aa.contract_no,
|
||||
ae.bus_no,
|
||||
ae.admit_source_code
|
||||
ae.admit_source_code,
|
||||
ae.status_enum,
|
||||
ap.id_card AS id_card,
|
||||
ao_zy.NAME AS organization_name
|
||||
FROM adm_encounter AS ae
|
||||
LEFT JOIN adm_organization AS ao_zy ON ao_zy.ID = ae.organization_id
|
||||
AND ao_zy.delete_flag = '0'
|
||||
LEFT JOIN adm_encounter AS ambae ON ae.amb_encounter_id = ambae.
|
||||
ID
|
||||
LEFT JOIN adm_organization AS ao ON ao.ID = ambae.organization_id
|
||||
@@ -52,6 +60,15 @@
|
||||
AND aa.type_code = '04'
|
||||
WHERE ae.delete_flag = '0'
|
||||
AND ae.class_enum = #{encounterClass}
|
||||
<if test='startTime != null'>
|
||||
AND ae.create_time >= #{startTime}
|
||||
</if>
|
||||
<if test='endTime != null'>
|
||||
AND ae.create_time <= #{endTime}
|
||||
</if>
|
||||
<if test='organizationId != null'>
|
||||
AND ae.organization_id = #{organizationId}
|
||||
</if>
|
||||
<if test="registeredFlag == '0'.toString()">
|
||||
AND ae.status_enum = #{encounterStatus}
|
||||
</if>
|
||||
|
||||
@@ -512,7 +512,7 @@
|
||||
personal_account.balance_amount,
|
||||
personal_account.id AS account_id,
|
||||
T2.category_code,
|
||||
ao.name AS org_name
|
||||
COALESCE(ao.name, al1."name") AS org_name
|
||||
FROM med_medication_request AS T1
|
||||
LEFT JOIN med_medication_definition AS T2
|
||||
ON T2.id = T1.medication_id
|
||||
|
||||
@@ -154,7 +154,11 @@
|
||||
ii.account_id AS account_id,
|
||||
ii.performer_check_id,
|
||||
ii.category_code,
|
||||
ii.dispense_status
|
||||
ii.dispense_status,
|
||||
ii.unit_price,
|
||||
ii.total_price,
|
||||
ii.stopper_id,
|
||||
ii.stopper_name
|
||||
FROM (( SELECT DISTINCT T1.encounter_id,
|
||||
T1.tenant_id,
|
||||
#{medMedicationRequest} AS advice_table,
|
||||
@@ -199,7 +203,11 @@
|
||||
personal_account.balance_amount,
|
||||
personal_account.id AS account_id,
|
||||
T2.category_code,
|
||||
mmd.status_enum AS dispense_status
|
||||
mmd.status_enum AS dispense_status,
|
||||
NULL::numeric AS unit_price,
|
||||
NULL::numeric AS total_price,
|
||||
NULL::bigint AS stopper_id,
|
||||
NULL::varchar AS stopper_name
|
||||
FROM med_medication_request AS T1
|
||||
LEFT JOIN med_medication_definition AS T2
|
||||
ON T2.id = T1.medication_id
|
||||
@@ -341,7 +349,11 @@
|
||||
personal_account.balance_amount,
|
||||
personal_account.id AS account_id,
|
||||
T2.category_code,
|
||||
NULL::integer AS dispense_status
|
||||
NULL::integer AS dispense_status,
|
||||
NULL::numeric AS unit_price,
|
||||
NULL::numeric AS total_price,
|
||||
NULL::bigint AS stopper_id,
|
||||
NULL::varchar AS stopper_name
|
||||
FROM wor_service_request AS T1
|
||||
LEFT JOIN wor_activity_definition AS T2
|
||||
ON T2.id = T1.activity_id
|
||||
@@ -427,6 +439,139 @@
|
||||
ELSE 1=1 END
|
||||
AND T1.refund_service_id IS NULL
|
||||
ORDER BY T1.status_enum )
|
||||
UNION
|
||||
( SELECT DISTINCT T1.encounter_id,
|
||||
T1.tenant_id,
|
||||
#{worDeviceRequest} AS advice_table,
|
||||
T1.id AS request_id,
|
||||
T1.req_authored_time AS start_time,
|
||||
NULL::timestamp AS end_time,
|
||||
T1.requester_id AS requester_id,
|
||||
T1.create_time AS request_time,
|
||||
NULL::integer AS skin_test_flag,
|
||||
NULL::integer AS inject_flag,
|
||||
NULL::bigint AS group_id,
|
||||
T1.performer_check_id,
|
||||
T2."name" AS advice_name,
|
||||
T2.id AS item_id,
|
||||
NULL::varchar AS volume,
|
||||
T1.lot_number AS lot_number,
|
||||
T1.quantity AS quantity,
|
||||
T1.unit_code AS unit_code,
|
||||
T1.status_enum AS request_status,
|
||||
NULL::varchar AS method_code,
|
||||
T1.rate_code AS rate_code,
|
||||
NULL::numeric AS dose,
|
||||
NULL::varchar AS dose_unit_code,
|
||||
ao1.id AS position_id,
|
||||
ao1."name" AS position_name,
|
||||
NULL::integer AS dispense_per_duration,
|
||||
1::numeric AS part_percent,
|
||||
ccd."name" AS condition_definition_name,
|
||||
NULL::integer AS therapy_enum,
|
||||
NULL::integer AS sort_number,
|
||||
T1.quantity AS execute_num,
|
||||
af.day_times,
|
||||
ae.bus_no,
|
||||
ap."name" AS patient_name,
|
||||
al2."name" AS bed_name,
|
||||
ap.gender_enum,
|
||||
ap.birth_date,
|
||||
ap.id AS patient_id,
|
||||
fc.contract_name,
|
||||
diagnosis.condition_names,
|
||||
pra."name" AS admitting_doctor_name,
|
||||
personal_account.balance_amount,
|
||||
personal_account.id AS account_id,
|
||||
T2.category_code,
|
||||
NULL::integer AS dispense_status,
|
||||
NULL::numeric AS unit_price,
|
||||
NULL::numeric AS total_price,
|
||||
NULL::bigint AS stopper_id,
|
||||
NULL::varchar AS stopper_name
|
||||
FROM wor_device_request AS T1
|
||||
LEFT JOIN adm_device_definition AS T2
|
||||
ON T2.id = T1.device_def_id
|
||||
AND T2.delete_flag = '0'
|
||||
LEFT JOIN adm_organization AS ao1
|
||||
ON ao1.id = T1.org_id
|
||||
AND ao1.delete_flag = '0'
|
||||
LEFT JOIN cli_condition AS cc
|
||||
ON cc.id = T1.condition_id
|
||||
AND cc.delete_flag = '0'
|
||||
LEFT JOIN cli_condition_definition AS ccd
|
||||
ON ccd.id = cc.definition_id
|
||||
AND ccd.delete_flag = '0'
|
||||
LEFT JOIN adm_encounter ae
|
||||
ON ae.id = T1.encounter_id
|
||||
AND ae.class_enum = #{imp}
|
||||
AND ae.delete_flag = '0'
|
||||
LEFT JOIN adm_patient ap
|
||||
ON ae.patient_id = ap.id
|
||||
AND ap.delete_flag = '0'
|
||||
LEFT JOIN adm_encounter_location ael
|
||||
ON ae.id = ael.encounter_id
|
||||
AND ael.delete_flag = '0'
|
||||
AND ael.status_enum = #{active}
|
||||
AND ael.form_enum = #{bed}
|
||||
LEFT JOIN adm_location al2
|
||||
ON ael.location_id = al2.id
|
||||
AND al2.delete_flag = '0'
|
||||
LEFT JOIN adm_account aa
|
||||
ON ae.id = aa.encounter_id
|
||||
AND aa.encounter_flag = 1
|
||||
AND aa.delete_flag = '0'
|
||||
LEFT JOIN fin_contract fc
|
||||
ON aa.contract_no = fc.bus_no
|
||||
AND fc.delete_flag = '0'
|
||||
LEFT JOIN ( SELECT aed.encounter_id,
|
||||
STRING_AGG(ccd.name, ', ') AS condition_names
|
||||
FROM adm_encounter_diagnosis aed
|
||||
INNER JOIN cli_condition cc
|
||||
ON cc.id = aed.condition_id
|
||||
AND cc.delete_flag = '0'
|
||||
INNER JOIN cli_condition_definition ccd
|
||||
ON ccd.id = cc.definition_id
|
||||
AND ccd.delete_flag = '0'
|
||||
WHERE aed.delete_flag = '0'
|
||||
GROUP BY aed.encounter_id
|
||||
) AS diagnosis
|
||||
ON ae.id = diagnosis.encounter_id
|
||||
LEFT JOIN adm_encounter_participant aep
|
||||
ON ae.id = aep.encounter_id
|
||||
AND aep.delete_flag = '0'
|
||||
AND aep.status_enum = #{active}
|
||||
AND aep.type_code = #{admittingDoctor}
|
||||
LEFT JOIN adm_practitioner pra
|
||||
ON aep.practitioner_id = pra.id
|
||||
AND pra.delete_flag = '0'
|
||||
LEFT JOIN ( SELECT aa.id,
|
||||
aa.encounter_id,
|
||||
(aa.balance_amount -
|
||||
COALESCE(SUM(CASE WHEN aci.status_enum IN (#{billed}, #{billable})
|
||||
THEN aci.total_price ELSE 0 END), 0) +
|
||||
COALESCE(SUM(CASE WHEN aci.status_enum = #{refunded}
|
||||
THEN aci.total_price ELSE 0 END), 0)) AS balance_amount
|
||||
FROM adm_account aa
|
||||
LEFT JOIN adm_charge_item aci
|
||||
ON aa.encounter_id = aci.encounter_id
|
||||
AND aa.delete_flag = '0'
|
||||
WHERE aa.type_code = #{personalCashAccount}
|
||||
AND aa.delete_flag = '0'
|
||||
GROUP BY aa.id,
|
||||
aa.encounter_id,
|
||||
aa.balance_amount
|
||||
) AS personal_account
|
||||
ON personal_account.encounter_id = ae.id
|
||||
LEFT JOIN adm_frequency af
|
||||
ON af.rate_code = T1.rate_code
|
||||
AND af.delete_flag = '0'
|
||||
WHERE T1.delete_flag = '0'
|
||||
AND T1.generate_source_enum = #{doctorPrescription}
|
||||
AND CASE WHEN T1.status_enum = #{draft}
|
||||
THEN FALSE
|
||||
ELSE TRUE END
|
||||
ORDER BY T1.status_enum )
|
||||
) AS ii
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
<collection property="medicineSummaryParamList" ofType="com.healthlink.his.web.inhospitalnursestation.dto.MedicineSummaryParam">
|
||||
<result property="procedureId" column="procedure_id"/>
|
||||
<result property="dispenseId" column="dispense_id"/>
|
||||
<result property="dispenseTime" column="planned_dispense_time"/>
|
||||
<result property="dispenseTime" column="execution_time"/>
|
||||
<result property="dispenseStatus" column="dispense_status"/>
|
||||
</collection>
|
||||
</resultMap>
|
||||
@@ -75,7 +75,7 @@
|
||||
ii.admitting_doctor_name,
|
||||
ii.balance_amount,
|
||||
ii.dispense_id,
|
||||
ii.planned_dispense_time,
|
||||
ii.execution_time,
|
||||
ii.procedure_id,
|
||||
ii.dispense_status
|
||||
FROM (( SELECT T1.encounter_id,
|
||||
@@ -113,7 +113,7 @@
|
||||
pra."name" AS admitting_doctor_name,
|
||||
personal_account.balance_amount,
|
||||
mmd.id AS dispense_id,
|
||||
mmd.planned_dispense_time,
|
||||
cp.occurrence_time AS execution_time,
|
||||
mmd.procedure_id,
|
||||
mmd.status_enum AS dispense_status
|
||||
FROM med_medication_request AS T1
|
||||
@@ -121,6 +121,9 @@
|
||||
ON T1.id = mmd.med_req_id
|
||||
AND mmd.delete_flag = '0'
|
||||
AND mmd.status_enum != #{summarized}
|
||||
LEFT JOIN cli_procedure cp
|
||||
ON cp.id = mmd.procedure_id
|
||||
AND cp.delete_flag = '0'
|
||||
LEFT JOIN med_medication_definition AS T2
|
||||
ON T2.id = T1.medication_id
|
||||
AND T2.delete_flag = '0'
|
||||
@@ -200,7 +203,7 @@
|
||||
AND T1.status_enum = #{completed}
|
||||
AND T1.refund_medicine_id IS NULL
|
||||
AND mmd.procedure_id IS NOT NULL
|
||||
ORDER BY mmd.planned_dispense_time )) AS ii
|
||||
ORDER BY cp.occurrence_time )) AS ii
|
||||
${ew.customSqlSegment}
|
||||
</select>
|
||||
<select id="selectMedicineSummaryFormPage"
|
||||
|
||||
@@ -190,6 +190,11 @@
|
||||
AND T9.status_enum = 2
|
||||
</if>
|
||||
|
||||
-- 待转科
|
||||
<if test="statusEnum == 2">
|
||||
AND T2.status_enum = 6
|
||||
</if>
|
||||
|
||||
-- 待出院
|
||||
<if test="statusEnum == 3">
|
||||
AND T2.status_enum = 4
|
||||
|
||||
@@ -4,89 +4,66 @@
|
||||
<!-- 病人信息相关查询-->
|
||||
<select id="getPatientPage" resultType="com.healthlink.his.web.patientmanage.dto.PatientBaseInfoDto">
|
||||
SELECT
|
||||
pt.identifier_no,
|
||||
pt.tenant_id,
|
||||
pt.id,
|
||||
pt.active_flag,
|
||||
pt.temp_flag,
|
||||
pt.name,
|
||||
pt.name_json,
|
||||
pt.bus_no,
|
||||
pt.gender_enum,
|
||||
pt.birth_date,
|
||||
pt.deceased_date,
|
||||
pt.marital_status_enum,
|
||||
pt.prfs_enum,
|
||||
pt.phone,
|
||||
pt.address,
|
||||
pt.address_province,
|
||||
pt.address_city,
|
||||
pt.address_district,
|
||||
pt.address_street,
|
||||
pt.address_json,
|
||||
pt.nationality_code,
|
||||
pt.id_card,
|
||||
pt.py_str,
|
||||
pt.wb_str,
|
||||
pt.blood_abo,
|
||||
pt.blood_rh,
|
||||
pt.work_company,
|
||||
pt.native_place,
|
||||
pt.country_code,
|
||||
pt.link_name,
|
||||
pt.link_relation_code,
|
||||
pt.link_telcom,
|
||||
pt.link_jsons,
|
||||
pt.organization_id,
|
||||
pt.create_time
|
||||
FROM (
|
||||
SELECT
|
||||
(
|
||||
SELECT api.identifier_no
|
||||
FROM adm_patient_identifier api
|
||||
WHERE api.tenant_id = p.tenant_id
|
||||
AND api.patient_id = p.id
|
||||
LIMIT 1
|
||||
) AS identifier_no,
|
||||
p.tenant_id,
|
||||
p.id,
|
||||
p.active_flag,
|
||||
p.temp_flag,
|
||||
p.name,
|
||||
p.name_json,
|
||||
p.bus_no,
|
||||
p.gender_enum,
|
||||
p.birth_date,
|
||||
p.deceased_date,
|
||||
p.marital_status_enum,
|
||||
p.prfs_enum,
|
||||
p.phone,
|
||||
p.address,
|
||||
p.address_province,
|
||||
p.address_city,
|
||||
p.address_district,
|
||||
p.address_street,
|
||||
p.address_json,
|
||||
p.nationality_code,
|
||||
p.id_card,
|
||||
p.py_str,
|
||||
p.wb_str,
|
||||
p.blood_abo,
|
||||
p.blood_rh,
|
||||
p.work_company,
|
||||
p.native_place,
|
||||
p.country_code,
|
||||
p.link_name,
|
||||
p.link_relation_code,
|
||||
p.link_telcom,
|
||||
p.link_jsons,
|
||||
p.organization_id,
|
||||
p.create_time
|
||||
FROM adm_patient p
|
||||
where p.delete_flag = '0'
|
||||
) AS pt
|
||||
${ew.customSqlSegment}
|
||||
ORDER BY pt.bus_no DESC
|
||||
(
|
||||
SELECT api.identifier_no
|
||||
FROM adm_patient_identifier api
|
||||
WHERE api.tenant_id = p.tenant_id
|
||||
AND api.patient_id = p.id
|
||||
LIMIT 1
|
||||
) AS identifier_no,
|
||||
p.tenant_id,
|
||||
p.id,
|
||||
p.active_flag,
|
||||
p.temp_flag,
|
||||
p.name,
|
||||
p.name_json,
|
||||
p.bus_no,
|
||||
p.gender_enum,
|
||||
p.birth_date,
|
||||
p.deceased_date,
|
||||
p.marital_status_enum,
|
||||
p.prfs_enum,
|
||||
p.phone,
|
||||
p.address,
|
||||
p.address_province,
|
||||
p.address_city,
|
||||
p.address_district,
|
||||
p.address_street,
|
||||
p.address_json,
|
||||
p.nationality_code,
|
||||
p.id_card,
|
||||
p.py_str,
|
||||
p.wb_str,
|
||||
p.blood_abo,
|
||||
p.blood_rh,
|
||||
p.work_company,
|
||||
p.native_place,
|
||||
p.country_code,
|
||||
p.link_name,
|
||||
p.link_relation_code,
|
||||
p.link_telcom,
|
||||
p.link_jsons,
|
||||
p.organization_id,
|
||||
p.create_time,
|
||||
p.postal_code,
|
||||
p.hukou_address,
|
||||
p.guardian_name,
|
||||
p.guardian_relation,
|
||||
p.guardian_phone,
|
||||
p.guardian_id_type,
|
||||
p.guardian_id_no,
|
||||
p.guardian_address,
|
||||
p.patient_derived,
|
||||
p.education_level,
|
||||
p.company_address
|
||||
FROM adm_patient p
|
||||
<where>
|
||||
p.delete_flag = '0'
|
||||
<if test="ew.sqlSegment != null and ew.sqlSegment != ''">
|
||||
AND ${ew.sqlSegment}
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY p.bus_no DESC
|
||||
</select>
|
||||
|
||||
<select id="getPatientIdInfo" resultType="com.healthlink.his.web.patientmanage.dto.PatientIdInfoDto">
|
||||
|
||||
@@ -97,10 +97,10 @@
|
||||
ON T4.med_req_id = T5.id
|
||||
AND T5.delete_flag = '0'
|
||||
WHERE <if test="statusEnum == null">
|
||||
T4.status_enum IN (#{inProgress},#{completed},#{preparation},#{prepared},#{summarized})
|
||||
T4.status_enum IN (#{draft},#{inProgress},#{completed},#{preparation},#{prepared},#{summarized})
|
||||
</if>
|
||||
<if test="statusEnum == 3">
|
||||
T4.status_enum IN (#{inProgress},#{preparation},#{prepared},#{summarized})
|
||||
T4.status_enum IN (#{draft},#{inProgress},#{preparation},#{prepared},#{summarized})
|
||||
</if>
|
||||
<if test="statusEnum == 4">
|
||||
T4.status_enum = #{completed}
|
||||
@@ -108,8 +108,9 @@
|
||||
<if test="statusEnum == 18">
|
||||
T4.status_enum = #{submitted}
|
||||
</if>
|
||||
AND T4.summary_no IS NOT NULL
|
||||
AND T4.summary_no != ''
|
||||
<if test="statusEnum == 1">
|
||||
T4.status_enum = #{draft}
|
||||
</if>
|
||||
) AS ii
|
||||
${ew.customSqlSegment}
|
||||
GROUP BY ii.encounter_id,
|
||||
@@ -268,14 +269,12 @@
|
||||
AND T15.delete_flag = '0'
|
||||
WHERE T1.delete_flag = '0'
|
||||
-- 因发药配药合并,前台只能看到待发药,已发药状态,但是后台配药发药状态都查
|
||||
AND T1.summary_no IS NOT NULL
|
||||
AND T1.summary_no != ''
|
||||
AND
|
||||
<if test="dispenseStatus == null">
|
||||
T1.status_enum IN (#{inProgress},#{completed},#{preparation},#{prepared},#{summarized})
|
||||
T1.status_enum IN (#{draft},#{inProgress},#{completed},#{preparation},#{prepared},#{summarized})
|
||||
</if>
|
||||
<if test="dispenseStatus == 3">
|
||||
T1.status_enum IN (#{inProgress},#{preparation},#{prepared},#{summarized})
|
||||
T1.status_enum IN (#{draft},#{inProgress},#{preparation},#{prepared},#{summarized})
|
||||
</if>
|
||||
<if test="dispenseStatus == 4">
|
||||
T1.status_enum = #{completed}
|
||||
@@ -283,6 +282,9 @@
|
||||
<if test="dispenseStatus == 18">
|
||||
T1.status_enum = #{submitted}
|
||||
</if>
|
||||
<if test="dispenseStatus == 1">
|
||||
T1.status_enum = #{draft}
|
||||
</if>
|
||||
AND T14.inventory_status_enum = #{active}
|
||||
ORDER BY prescription_no DESC
|
||||
) AS ii
|
||||
|
||||
@@ -220,8 +220,8 @@
|
||||
T1.based_on_id AS based_on_id,
|
||||
T1.medication_id AS advice_definition_id,
|
||||
T1.content_json::jsonb ->> 'remark' AS remark,
|
||||
T1.effective_dose_end AS stop_time,
|
||||
T1.update_by AS stop_user_name
|
||||
CASE WHEN T1.status_enum = 6 THEN T1.effective_dose_end ELSE NULL END AS stop_time,
|
||||
CASE WHEN T1.status_enum = 6 THEN T1.update_by ELSE NULL END AS stop_user_name
|
||||
FROM med_medication_request AS T1
|
||||
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
|
||||
AND T2.delete_flag = '0'
|
||||
@@ -306,7 +306,7 @@
|
||||
null AS skin_test_flag,
|
||||
null AS inject_flag,
|
||||
null AS group_id,
|
||||
COALESCE(T2.NAME, T1.content_json::jsonb->>'surgeryName', T1.content_json::jsonb->>'adviceName') AS advice_name,
|
||||
COALESCE(T1.content_json::jsonb->>'adviceName', T2.NAME, T1.content_json::jsonb->>'surgeryName') AS advice_name,
|
||||
'' AS volume,
|
||||
'' AS lot_number,
|
||||
T1.quantity AS quantity,
|
||||
@@ -331,8 +331,8 @@
|
||||
T1.based_on_id AS based_on_id,
|
||||
T1.activity_id AS advice_definition_id,
|
||||
T1.remark AS remark,
|
||||
T1.occurrence_end_time AS stop_time,
|
||||
T1.update_by AS stop_user_name
|
||||
CASE WHEN T1.status_enum = 6 THEN T1.occurrence_end_time ELSE NULL END AS stop_time,
|
||||
CASE WHEN T1.status_enum = 6 THEN T1.update_by ELSE NULL END AS stop_user_name
|
||||
FROM wor_service_request AS T1
|
||||
LEFT JOIN wor_activity_definition AS T2
|
||||
ON T2.ID = T1.activity_id
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
</select>
|
||||
|
||||
<select id="getRequestFormDetail" resultType="com.healthlink.his.web.regdoctorstation.dto.RequestFormDetailQueryDto">
|
||||
SELECT wsr.activity_id AS activity_id,
|
||||
SELECT wsr.activity_id AS advice_definition_id,
|
||||
wsr.quantity,
|
||||
wsr.unit_code,
|
||||
COALESCE(wad.NAME, wsr.content_json::jsonb->>'surgeryName') AS advice_name,
|
||||
|
||||
@@ -9,14 +9,16 @@ import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@@ -24,137 +26,154 @@ public class DictAspect {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DictAspect.class);
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate; // 使用 JdbcTemplate 执行 SQL
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
public DictAspect(JdbcTemplate jdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
}
|
||||
|
||||
@Around("@annotation(org.springframework.web.bind.annotation.GetMapping) || "
|
||||
+ "@annotation(org.springframework.web.bind.annotation.PostMapping)")
|
||||
public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
Object result = joinPoint.proceed(); // 执行原方法
|
||||
Object result = joinPoint.proceed();
|
||||
|
||||
if (result instanceof R<?> response) {
|
||||
Object data = response.getData(); // 获取 R<?> 中的实际数据
|
||||
|
||||
if (data instanceof Page) {
|
||||
// 如果数据是 Page 类型,处理分页数据
|
||||
Page<?> page = (Page<?>)data;
|
||||
List<?> records = page.getRecords();
|
||||
if (!records.isEmpty()) {
|
||||
try {
|
||||
if (result instanceof R<?> response) {
|
||||
Object data = response.getData();
|
||||
if (data instanceof Page<?> page) {
|
||||
List<?> records = page.getRecords();
|
||||
for (Object obj : records) {
|
||||
processDict(obj); // 处理每个 DTO 对象
|
||||
processDict(obj, new HashSet<>());
|
||||
}
|
||||
}
|
||||
} else if (data instanceof List<?> list) {
|
||||
if (!list.isEmpty()) {
|
||||
} else if (data instanceof List<?> list) {
|
||||
for (Object obj : list) {
|
||||
processDict(obj); // 处理每个 DTO 对象
|
||||
processDict(obj, new HashSet<>());
|
||||
}
|
||||
} else if (data != null) {
|
||||
processDict(data, new HashSet<>());
|
||||
}
|
||||
} else {
|
||||
// 如果数据是单个 DTO 对象,直接处理
|
||||
processDict(data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("字典翻译处理异常,跳过字典处理", e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private <T> void processDict(T dto) throws IllegalAccessException {
|
||||
private void processDict(Object dto, Set<Integer> visited) {
|
||||
if (dto == null) {
|
||||
return;
|
||||
}
|
||||
// 检查对象是否是 DTO 类(即是否有 @Dict 注解的字段)
|
||||
boolean isDto = false;
|
||||
for (Field field : dto.getClass().getDeclaredFields()) {
|
||||
int identityHash = System.identityHashCode(dto);
|
||||
if (!visited.add(identityHash)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> clazz = dto.getClass();
|
||||
if (clazz.isPrimitive() || clazz.getName().startsWith("java.lang.")
|
||||
|| dto instanceof java.math.BigDecimal || dto instanceof java.util.Date
|
||||
|| dto instanceof java.time.temporal.TemporalAccessor
|
||||
|| dto instanceof byte[] || dto instanceof char[]) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<Field> allFields = collectFields(clazz);
|
||||
boolean hasDict = false;
|
||||
for (Field field : allFields) {
|
||||
if (field.isAnnotationPresent(Dict.class)) {
|
||||
isDto = true;
|
||||
hasDict = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 如果不是 DTO 类,直接返回
|
||||
if (!isDto) {
|
||||
if (!hasDict) {
|
||||
return;
|
||||
}
|
||||
// 获取 DTO 类的所有字段
|
||||
for (Field field : dto.getClass().getDeclaredFields()) {
|
||||
field.setAccessible(true); // 设置字段可访问
|
||||
Object fieldValue = field.get(dto); // 获取字段值
|
||||
|
||||
for (Field field : allFields) {
|
||||
field.setAccessible(true);
|
||||
Object fieldValue;
|
||||
try {
|
||||
fieldValue = field.get(dto);
|
||||
} catch (IllegalAccessException e) {
|
||||
log.debug("无法访问字段 {}.{}", clazz.getSimpleName(), field.getName());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fieldValue == null) {
|
||||
continue; // 如果字段值为空,跳过
|
||||
continue;
|
||||
}
|
||||
// 如果字段是 List 类型,递归处理其中的每个元素
|
||||
if (fieldValue instanceof List<?> list) {
|
||||
for (Object item : list) {
|
||||
processDict(item); // 递归处理 List 中的每个元素
|
||||
processDict(item, visited);
|
||||
}
|
||||
} else if (field.isAnnotationPresent(Dict.class)) {
|
||||
// 如果字段带有 @Dict 注解,处理字典值
|
||||
Dict dictAnnotation = field.getAnnotation(Dict.class);
|
||||
String dictCode = dictAnnotation.dictCode();
|
||||
String dictText = dictAnnotation.dictText();
|
||||
String dictTable = dictAnnotation.dictTable();
|
||||
String deleteFlag = dictAnnotation.deleteFlag();
|
||||
|
||||
// 检查 _dictText 字段是否已被手动填充(如控制器方法中预先查询设置)
|
||||
// 如果已非空则跳过 SQL 查询,避免覆盖有效值
|
||||
String textFieldName = field.getName() + "_dictText";
|
||||
try {
|
||||
Field existingTextField = dto.getClass().getDeclaredField(textFieldName);
|
||||
Field existingTextField = clazz.getDeclaredField(textFieldName);
|
||||
existingTextField.setAccessible(true);
|
||||
Object existingValue = existingTextField.get(dto);
|
||||
if (existingValue != null && !existingValue.toString().isEmpty()) {
|
||||
continue; // _dictText 已有值,跳过
|
||||
continue;
|
||||
}
|
||||
} catch (NoSuchFieldException e) {
|
||||
// _dictText 字段不存在,继续正常流程
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
// _dictText field not present, proceed normally
|
||||
}
|
||||
|
||||
// 查询字典值
|
||||
String dictLabel = queryDictLabel(dictTable, dictCode, dictText, deleteFlag, fieldValue.toString());
|
||||
if (dictLabel != null && !dictLabel.isEmpty()) {
|
||||
// 动态生成 _dictText 字段名
|
||||
try {
|
||||
Field textField = dto.getClass().getDeclaredField(textFieldName);
|
||||
textField.setAccessible(true);
|
||||
textField.set(dto, dictLabel); // 设置 _dictText 字段的值
|
||||
} catch (NoSuchFieldException e) {
|
||||
// 如果 _dictText 字段不存在,忽略错误
|
||||
log.debug("字段 {} 不存在,跳过字典翻译", textFieldName);
|
||||
try {
|
||||
String dictLabel = queryDictLabel(dictTable, dictCode, dictText, deleteFlag, fieldValue.toString());
|
||||
if (dictLabel != null && !dictLabel.isEmpty()) {
|
||||
try {
|
||||
Field textField = clazz.getDeclaredField(textFieldName);
|
||||
textField.setAccessible(true);
|
||||
textField.set(dto, dictLabel);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
log.debug("字段 {} 不存在或无法访问,跳过字典翻译", textFieldName);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("字典翻译异常, 字段={}, dictCode={}, 跳过: {}", field.getName(), dictCode, e.getMessage());
|
||||
}
|
||||
} else {
|
||||
processDict(fieldValue); // 递归处理 Dto 中的每个元素
|
||||
processDict(fieldValue, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Field> collectFields(Class<?> clazz) {
|
||||
List<Field> fields = new ArrayList<>();
|
||||
Class<?> current = clazz;
|
||||
while (current != null && current != Object.class) {
|
||||
for (Field field : current.getDeclaredFields()) {
|
||||
fields.add(field);
|
||||
}
|
||||
current = current.getSuperclass();
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
private String queryDictLabel(String dictTable, String dictCode, String dictText, String deleteFlag, String dictValue) {
|
||||
if (!StringUtils.hasText(dictTable)) {
|
||||
// 场景 1:默认字典走DictUtils缓存(dictTable 为空时)
|
||||
return DictUtils.getDictLabel(dictCode, dictValue);
|
||||
} else {
|
||||
// 场景 2:查询指定表(dictTable 有值时)
|
||||
// 必须同时有 dictTable 和 dictText 才能执行 SQL 查询
|
||||
if (!StringUtils.hasText(dictText)) {
|
||||
// 如果 dictText 为空,回退到字典缓存查询
|
||||
return DictUtils.getDictLabel(dictCode, dictValue);
|
||||
}
|
||||
// 构建SQL,支持 delete_flag 过滤
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append(String.format("SELECT %s FROM %s WHERE %s::varchar = ?", dictText, dictTable, dictCode));
|
||||
// 如果指定了 deleteFlag 字段名,添加过滤条件
|
||||
if (StringUtils.hasText(deleteFlag)) {
|
||||
sqlBuilder.append(String.format(" AND %s = '0'", deleteFlag));
|
||||
}
|
||||
sqlBuilder.append(" LIMIT 1");
|
||||
String sql = sqlBuilder.toString();
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(sql, String.class, dictValue);
|
||||
} catch (DataAccessException e) {
|
||||
// 如果查询结果为空,返回 空字符串
|
||||
return "";
|
||||
}
|
||||
}
|
||||
if (!StringUtils.hasText(dictText)) {
|
||||
return DictUtils.getDictLabel(dictCode, dictValue);
|
||||
}
|
||||
StringBuilder sqlBuilder = new StringBuilder();
|
||||
sqlBuilder.append(String.format("SELECT %s FROM %s WHERE %s::varchar = ?", dictText, dictTable, dictCode));
|
||||
if (StringUtils.hasText(deleteFlag)) {
|
||||
sqlBuilder.append(String.format(" AND %s = '0'", deleteFlag));
|
||||
}
|
||||
sqlBuilder.append(" LIMIT 1");
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(sqlBuilder.toString(), String.class, dictValue);
|
||||
} catch (DataAccessException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ public enum EncounterZyStatus implements HisEnumInterface {
|
||||
|
||||
PENDING_TRANSFER(6, "pending-transfer", "待转科"),
|
||||
|
||||
ALREADY_SETTLED(7, "already-settled", "已结算出院");
|
||||
ALREADY_SETTLED(7, "already-settled", "已结算出院"),
|
||||
|
||||
VOIDED(8, "voided", "已作废");
|
||||
|
||||
@EnumValue
|
||||
private final Integer value;
|
||||
|
||||
@@ -130,4 +130,37 @@ public class Patient extends HisBaseEntity {
|
||||
/** 机构Id */
|
||||
private Long organizationId;
|
||||
|
||||
/** 邮政编码 */
|
||||
private String postalCode;
|
||||
|
||||
/** 户籍地址 */
|
||||
private String hukouAddress;
|
||||
|
||||
/** 监护人姓名 */
|
||||
private String guardianName;
|
||||
|
||||
/** 监护人关系 */
|
||||
private Integer guardianRelation;
|
||||
|
||||
/** 监护人电话 */
|
||||
private String guardianPhone;
|
||||
|
||||
/** 监护人证件类型 */
|
||||
private String guardianIdType;
|
||||
|
||||
/** 监护人证件号码 */
|
||||
private String guardianIdNo;
|
||||
|
||||
/** 监护人地址 */
|
||||
private String guardianAddress;
|
||||
|
||||
/** 患者来源 */
|
||||
private String patientDerived;
|
||||
|
||||
/** 文化程度 */
|
||||
private String educationLevel;
|
||||
|
||||
/** 单位地址 */
|
||||
private String companyAddress;
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public class TicketSlotDTO {
|
||||
private String patientName;
|
||||
private String medicalCard;
|
||||
private Long patientId;
|
||||
private Long realPatientId;
|
||||
private String phone;
|
||||
private Integer orderStatus;
|
||||
private Long orderId;
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
o.order_no AS orderNo,
|
||||
COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender,
|
||||
pinfo.gender_enum AS genderEnum,
|
||||
pinfo.id AS realPatientId,
|
||||
pinfo.id_card AS idCard,
|
||||
o.appointment_time AS appointmentTime,
|
||||
<include refid="orderStatusNormExpr" /> AS orderStatus,
|
||||
@@ -230,6 +231,7 @@
|
||||
o.order_no AS orderNo,
|
||||
COALESCE(CAST(o.gender AS VARCHAR), CAST(pinfo.gender_enum AS VARCHAR)) AS patientGender,
|
||||
pinfo.gender_enum AS genderEnum,
|
||||
pinfo.id AS realPatientId,
|
||||
pinfo.id_card AS idCard,
|
||||
o.appointment_time AS appointmentTime,
|
||||
<include refid="orderStatusNormExpr" /> AS orderStatus,
|
||||
|
||||
@@ -4,7 +4,7 @@ rem 设置项目根目录
|
||||
set PROJECT_ROOT=%~dp0
|
||||
|
||||
rem 设置classpath
|
||||
set CLASSPATH=%PROJECT_ROOT%openhis-application\target\classes;%PROJECT_ROOT%openhis-domain\target\classes;%PROJECT_ROOT%openhis-common\target\classes;%PROJECT_ROOT%core-admin\target\classes;%PROJECT_ROOT%core-framework\target\classes;%PROJECT_ROOT%core-system\target\classes;%PROJECT_ROOT%core-quartz\target\classes;%PROJECT_ROOT%core-generator\target\classes;%PROJECT_ROOT%core-flowable\target\classes;%PROJECT_ROOT%core-common\target\classes
|
||||
set CLASSPATH=%PROJECT_ROOT%healthlink-his-application\target\classes;%PROJECT_ROOT%healthlink-his-domain\target\classes;%PROJECT_ROOT%healthlink-his-common\target\classes;%PROJECT_ROOT%core-admin\target\classes;%PROJECT_ROOT%core-framework\target\classes;%PROJECT_ROOT%core-system\target\classes;%PROJECT_ROOT%core-quartz\target\classes;%PROJECT_ROOT%core-generator\target\classes;%PROJECT_ROOT%core-flowable\target\classes;%PROJECT_ROOT%core-common\target\classes
|
||||
|
||||
rem 启动应用
|
||||
java -cp "%CLASSPATH%" com.openhis.OpenHisApplication
|
||||
java -cp "%CLASSPATH%" com.healthlink.his.HealthLinkHisApplication
|
||||
@@ -4,10 +4,10 @@
|
||||
PROJECT_ROOT=$(pwd)
|
||||
|
||||
# 设置classpath
|
||||
CLASSPATH="$PROJECT_ROOT/openhis-application/target/classes:$PROJECT_ROOT/openhis-domain/target/classes:$PROJECT_ROOT/openhis-common/target/classes:$PROJECT_ROOT/core-admin/target/classes:$PROJECT_ROOT/core-framework/target/classes:$PROJECT_ROOT/core-system/target/classes:$PROJECT_ROOT/core-quartz/target/classes:$PROJECT_ROOT/core-generator/target/classes:$PROJECT_ROOT/core-flowable/target/classes:$PROJECT_ROOT/core-common/target/classes"
|
||||
CLASSPATH="$PROJECT_ROOT/healthlink-his-application/target/classes:$PROJECT_ROOT/healthlink-his-domain/target/classes:$PROJECT_ROOT/healthlink-his-common/target/classes:$PROJECT_ROOT/core-admin/target/classes:$PROJECT_ROOT/core-framework/target/classes:$PROJECT_ROOT/core-system/target/classes:$PROJECT_ROOT/core-quartz/target/classes:$PROJECT_ROOT/core-generator/target/classes:$PROJECT_ROOT/core-flowable/target/classes:$PROJECT_ROOT/core-common/target/classes"
|
||||
|
||||
# 添加所有依赖jar包
|
||||
export CLASSPATH="$CLASSPATH:$(find $PROJECT_ROOT/openhis-application/target/dependency -name '*.jar' | tr '\n' ':')"
|
||||
export CLASSPATH="$CLASSPATH:$(find $PROJECT_ROOT/healthlink-his-application/target/dependency -name '*.jar' | tr '\n' ':')"
|
||||
|
||||
# 启动应用
|
||||
java -cp "$CLASSPATH" com.openhis.OpenHisApplication
|
||||
java -cp "$CLASSPATH" com.healthlink.his.HealthLinkHisApplication
|
||||
@@ -1,8 +0,0 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE =医院信息管理系统
|
||||
|
||||
# 开发环境配置
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
# HealthLink-HIS管理系统/开发环境
|
||||
VITE_APP_BASE_API = '/dev-api'
|
||||
@@ -1,14 +0,0 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE=医院信息管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV= 'prod'
|
||||
|
||||
# HealthLink-HIS管理系统/生产环境
|
||||
VITE_APP_BASE_API= '/prd-api'
|
||||
|
||||
# 租户ID配置
|
||||
VITE_APP_TENANT_ID= '1'
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
VITE_BUILD_COMPRESS = gzip
|
||||
@@ -1,38 +0,0 @@
|
||||
# 开发环境:本地只启动前端项目,依赖开发环境(后端、APP)
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'spug'
|
||||
|
||||
VITE_DEV=true
|
||||
|
||||
# 请求路径
|
||||
VITE_BASE_URL='http://192.168.110.252'
|
||||
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||
VITE_UPLOAD_TYPE=server
|
||||
|
||||
# HealthLink-HIS管理系统/SPUG环境
|
||||
VITE_APP_BASE_API = '/admin-api'
|
||||
|
||||
# 租户ID配置
|
||||
VITE_APP_TENANT_ID=1
|
||||
|
||||
# 是否删除debugger
|
||||
VITE_DROP_DEBUGGER=false
|
||||
|
||||
# 是否删除console.log
|
||||
VITE_DROP_CONSOLE=false
|
||||
|
||||
# 是否sourcemap
|
||||
VITE_SOURCEMAP=true
|
||||
|
||||
# 打包路径
|
||||
VITE_BASE_PATH=/
|
||||
|
||||
# 商城H5会员端域名
|
||||
VITE_MALL_H5_DOMAIN='http://mall.yudao.iocoder.cn'
|
||||
|
||||
# 验证码的开关
|
||||
VITE_APP_CAPTCHA_ENABLE=false
|
||||
|
||||
# GoView域名
|
||||
VITE_GOVIEW_URL='http://127.0.0.1:3000'
|
||||
@@ -1,14 +0,0 @@
|
||||
# 页面标题
|
||||
VITE_APP_TITLE = OpenHIS管理系统
|
||||
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV = 'staging'
|
||||
|
||||
# OpenHIS管理系统/生产环境
|
||||
VITE_APP_BASE_API = '/stage-api'
|
||||
|
||||
# 租户ID配置
|
||||
VITE_APP_TENANT_ID=1
|
||||
|
||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
||||
VITE_BUILD_COMPRESS = gzip
|
||||
@@ -1,5 +0,0 @@
|
||||
# Playwright E2E 测试环境变量
|
||||
# 注意:此文件仅用于本地开发,生产环境使用CI Secret管理
|
||||
TEST_BASE_URL=http://localhost:80
|
||||
TEST_USERNAME=admin
|
||||
TEST_PASSWORD=changeme_in_local_env
|
||||
@@ -1,8 +1,12 @@
|
||||
/* eslint-env node */
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import globals from "globals";
|
||||
import pluginVue from "eslint-plugin-vue";
|
||||
import parserVue from "vue-eslint-parser";
|
||||
import importPlugin from "eslint-plugin-import";
|
||||
import importPlugin, { createNodeResolver } from "eslint-plugin-import-x";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export default [
|
||||
{
|
||||
@@ -29,31 +33,31 @@ export default [
|
||||
},
|
||||
|
||||
plugins: {
|
||||
import: importPlugin,
|
||||
"import-x": importPlugin,
|
||||
},
|
||||
|
||||
rules: {
|
||||
// 确保导入的模块实际存在(核心规则,防止构建失败)
|
||||
"import/no-unresolved": "error",
|
||||
"import-x/no-unresolved": "error",
|
||||
// 确保导入的命名导出实际存在
|
||||
"import/named": "error",
|
||||
"import-x/named": "error",
|
||||
// 确保默认导出存在
|
||||
"import/default": "error",
|
||||
"import-x/default": "error",
|
||||
// 确保命名空间导出存在
|
||||
"import/namespace": "error",
|
||||
"import-x/namespace": "error",
|
||||
// Vue 相关规则
|
||||
"vue/multi-word-component-names": "off",
|
||||
},
|
||||
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
alias: {
|
||||
map: [
|
||||
["@", "./src"],
|
||||
],
|
||||
extensions: [".js", ".jsx", ".vue"],
|
||||
},
|
||||
},
|
||||
"import-x/resolver-next": [
|
||||
createNodeResolver({
|
||||
alias: {
|
||||
"@": [path.join(__dirname, "src")],
|
||||
},
|
||||
extensions: [".mjs", ".cjs", ".js", ".jsx", ".vue", ".json", ".node"],
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -75,8 +75,7 @@
|
||||
"@vitejs/plugin-vue": "^5.2.4",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"eslint": "^10.4.1",
|
||||
"eslint-import-resolver-alias": "^1.1.2",
|
||||
"eslint-plugin-import": "^2.32.0",
|
||||
"eslint-plugin-import-x": "^4.16.1",
|
||||
"eslint-plugin-vue": "^10.9.1",
|
||||
"globals": "^17.5.0",
|
||||
"happy-dom": "^20.8.3",
|
||||
|
||||
@@ -2,51 +2,51 @@ import request from '@/utils/request'
|
||||
|
||||
// ==================== 处方审核 ====================
|
||||
export function auditPrescription(data) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/audit', method: 'post', data })
|
||||
return request({ url: '/api/v1/rational-drug/audit', method: 'post', data })
|
||||
}
|
||||
|
||||
export function batchAudit(prescriptionIds) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/batch-audit', method: 'post', data: prescriptionIds })
|
||||
return request({ url: '/api/v1/rational-drug/batch-audit', method: 'post', data: prescriptionIds })
|
||||
}
|
||||
|
||||
export function getAuditStatistics() {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/statistics', method: 'get' })
|
||||
return request({ url: '/api/v1/rational-drug/statistics', method: 'get' })
|
||||
}
|
||||
|
||||
export function getAuditTrend(startDate) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/trend', method: 'get', params: { startDate } })
|
||||
return request({ url: '/api/v1/rational-drug/trend', method: 'get', params: { startDate } })
|
||||
}
|
||||
|
||||
export function getAuditLog(encounterId) {
|
||||
return request({ url: `/healthlink-his/api/v1/rational-drug/audit-log/${encounterId}`, method: 'get' })
|
||||
return request({ url: `/api/v1/rational-drug/audit-log/${encounterId}`, method: 'get' })
|
||||
}
|
||||
|
||||
// ==================== 配伍禁忌 ====================
|
||||
export function checkInteraction(drugCodes) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/check-interaction', method: 'post', data: drugCodes })
|
||||
return request({ url: '/api/v1/rational-drug/check-interaction', method: 'post', data: drugCodes })
|
||||
}
|
||||
|
||||
export function listInteractionRules(params) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/interaction-rules', method: 'get', params })
|
||||
return request({ url: '/api/v1/rational-drug/interaction-rules', method: 'get', params })
|
||||
}
|
||||
|
||||
export function addInteractionRule(data) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/interaction-rules', method: 'post', data })
|
||||
return request({ url: '/api/v1/rational-drug/interaction-rules', method: 'post', data })
|
||||
}
|
||||
|
||||
export function updateInteractionRule(data) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/interaction-rules', method: 'put', data })
|
||||
return request({ url: '/api/v1/rational-drug/interaction-rules', method: 'put', data })
|
||||
}
|
||||
|
||||
export function delInteractionRule(id) {
|
||||
return request({ url: `/healthlink-his/api/v1/rational-drug/interaction-rules/${id}`, method: 'delete' })
|
||||
return request({ url: `/api/v1/rational-drug/interaction-rules/${id}`, method: 'delete' })
|
||||
}
|
||||
|
||||
// ==================== 剂量规则 ====================
|
||||
export function listDosageRules(params) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/dosage-rules', method: 'get', params })
|
||||
return request({ url: '/api/v1/rational-drug/dosage-rules', method: 'get', params })
|
||||
}
|
||||
|
||||
export function checkDosage(drugCode, dosage, population) {
|
||||
return request({ url: '/healthlink-his/api/v1/rational-drug/check-dosage', method: 'get', params: { drugCode, dosage, population } })
|
||||
return request({ url: '/api/v1/rational-drug/check-dosage', method: 'get', params: { drugCode, dosage, population } })
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import request from '@/utils/request'
|
||||
// 处方审核
|
||||
export function auditPrescription(data) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/audit',
|
||||
url: '/api/v1/rational-drug/audit',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
@@ -12,7 +12,7 @@ export function auditPrescription(data) {
|
||||
// 批量审核
|
||||
export function batchAudit(data) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/batch-audit',
|
||||
url: '/api/v1/rational-drug/batch-audit',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
@@ -21,7 +21,7 @@ export function batchAudit(data) {
|
||||
// 审核统计
|
||||
export function getAuditStatistics() {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/statistics',
|
||||
url: '/api/v1/rational-drug/statistics',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -29,7 +29,7 @@ export function getAuditStatistics() {
|
||||
// 审核趋势
|
||||
export function getAuditTrend(params) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/trend',
|
||||
url: '/api/v1/rational-drug/trend',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
@@ -38,7 +38,7 @@ export function getAuditTrend(params) {
|
||||
// 审核记录
|
||||
export function getAuditLog(encounterId) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/audit-log/' + encounterId,
|
||||
url: '/api/v1/rational-drug/audit-log/' + encounterId,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -46,7 +46,7 @@ export function getAuditLog(encounterId) {
|
||||
// 配伍禁忌检查
|
||||
export function checkInteraction(data) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/check-interaction',
|
||||
url: '/api/v1/rational-drug/check-interaction',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
@@ -55,7 +55,7 @@ export function checkInteraction(data) {
|
||||
// 配伍禁忌规则列表
|
||||
export function listInteractionRules(params) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/interaction-rules',
|
||||
url: '/api/v1/rational-drug/interaction-rules',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
@@ -64,7 +64,7 @@ export function listInteractionRules(params) {
|
||||
// 新增配伍禁忌规则
|
||||
export function addInteractionRule(data) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/interaction-rules',
|
||||
url: '/api/v1/rational-drug/interaction-rules',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
@@ -73,7 +73,7 @@ export function addInteractionRule(data) {
|
||||
// 修改配伍禁忌规则
|
||||
export function updateInteractionRule(data) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/interaction-rules',
|
||||
url: '/api/v1/rational-drug/interaction-rules',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
@@ -82,7 +82,7 @@ export function updateInteractionRule(data) {
|
||||
// 删除配伍禁忌规则
|
||||
export function delInteractionRule(id) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/interaction-rules/' + id,
|
||||
url: '/api/v1/rational-drug/interaction-rules/' + id,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
@@ -90,7 +90,7 @@ export function delInteractionRule(id) {
|
||||
// 剂量规则列表
|
||||
export function listDosageRules(params) {
|
||||
return request({
|
||||
url: '/healthlink-his/api/v1/rational-drug/dosage-rules',
|
||||
url: '/api/v1/rational-drug/dosage-rules',
|
||||
method: 'get',
|
||||
params: params
|
||||
})
|
||||
|
||||
@@ -71,6 +71,14 @@ router.beforeEach(async (to, from) => {
|
||||
return { path: '/login' }
|
||||
}
|
||||
}
|
||||
// 铁律: 路由权限校验 — 目标路由必须在已注册的路由中存在
|
||||
// 防止切换账户后,通过旧标签或直接输入 URL 访问无权限页面
|
||||
const resolved = router.resolve(to)
|
||||
if (resolved.matched.length === 0 || resolved.name === 'NotFound') {
|
||||
// 路由不存在(未注册),拒绝导航
|
||||
ElMessage.warning('无权访问该页面')
|
||||
return { path: '/' }
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
if (isWhiteList(to.path)) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {getInfo, login, logout} from '@/api/login'
|
||||
import useTagsViewStore from '@/store/modules/tagsView'
|
||||
import {getToken, removeToken, setToken} from '@/utils/auth'
|
||||
import defAva from '@/assets/images/user.png'
|
||||
import {defineStore} from 'pinia'
|
||||
@@ -84,6 +85,8 @@ const useUserStore = defineStore(
|
||||
this.permissions = []
|
||||
this.tenantId = ''
|
||||
removeToken()
|
||||
// 清除标签页内存状态,防止切换账户时残留
|
||||
try { useTagsViewStore().delAllViews() } catch(e) {}
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
ref="patientListRef"
|
||||
height="620"
|
||||
:data="patientList"
|
||||
:row-config="{ keyField: 'encounterId', keyField: 'id' }"
|
||||
:row-config="{ keyField: 'encounterId' }"
|
||||
@cell-click="clickRow"
|
||||
>
|
||||
<vxe-column
|
||||
@@ -447,7 +447,8 @@ function checkSelectable(row, index) {
|
||||
/**
|
||||
* 点击患者列表行 获取处方列表
|
||||
*/
|
||||
function clickRow(row) {
|
||||
function clickRow(params) {
|
||||
const row = params.row || params;
|
||||
patientInfo.value = row;
|
||||
chargeLoading.value = true;
|
||||
encounterId.value = row.encounterId;
|
||||
|
||||
@@ -447,15 +447,65 @@
|
||||
v-model="form.deceasedDate"
|
||||
type="datetime"
|
||||
placeholder="请选择时间"
|
||||
format="YYYY/MM/DD HH:mm:ss"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
:disabled="isViewMode"
|
||||
value-format="YYYY/MM/DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 第八行:监护人、监护人关系、监护人电话 -->
|
||||
|
||||
<!-- 第八行:联系人、联系人关系、联系人电话 -->
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item
|
||||
label="联系人"
|
||||
prop="linkName"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.linkName"
|
||||
clearable
|
||||
:disabled="isViewMode"
|
||||
placeholder="请输入联系人"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item
|
||||
label="联系人关系"
|
||||
prop="linkRelationCode"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.linkRelationCode"
|
||||
placeholder="联系人关系"
|
||||
clearable
|
||||
:disabled="isViewMode"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in link_relation_code"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item
|
||||
label="联系人电话"
|
||||
prop="linkTelcom"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.linkTelcom"
|
||||
clearable
|
||||
:disabled="isViewMode"
|
||||
placeholder="请输入联系人电话"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<!-- 第九行:监护人、监护人关系、监护人电话 -->
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item
|
||||
@@ -702,12 +752,26 @@ const getGenderOptions = async () => {
|
||||
const getEducationLevelOptions = async () => {
|
||||
try {
|
||||
// 从字典管理获取文化程度数据
|
||||
const response = await getDicts('文化程度');
|
||||
const response = await getDicts('educational_level');
|
||||
console.log('获取到的文化程度原始数据:', response);
|
||||
|
||||
// 确保数据是数组
|
||||
if (!response || response.code !== 200 || !Array.isArray(response.data)) {
|
||||
console.error('文化程度数据格式错误:', response);
|
||||
// 确保数据是数组且非空
|
||||
if (!response || response.code !== 200 || !Array.isArray(response.data) || response.data.length === 0) {
|
||||
console.warn('文化程度数据为空或格式错误,使用默认数据:', response);
|
||||
// 降级方案:使用默认的文化程度选项,按编码顺序排列
|
||||
educationLevelList.value = [
|
||||
{ value: '1', info: '大学本科' },
|
||||
{ value: '2', info: '硕士研究生' },
|
||||
{ value: '3', info: '博士研究生' },
|
||||
{ value: '4', info: '初中毕业' },
|
||||
{ value: '5', info: '大学专科结业' },
|
||||
{ value: '6', info: '技工学院结业' },
|
||||
{ value: '7', info: '职业高中结业' },
|
||||
{ value: '8', info: '小学毕业' },
|
||||
{ value: '9', info: '普通高中结业' },
|
||||
{ value: '10', info: '中等专科结业' },
|
||||
{ value: '99', info: '其他' }
|
||||
];
|
||||
return;
|
||||
}
|
||||
const educationDict = response.data;
|
||||
@@ -743,17 +807,18 @@ const getEducationLevelOptions = async () => {
|
||||
console.error('获取文化程度字典数据失败:', error);
|
||||
// 降级方案:使用默认的文化程度选项,按编码顺序排列
|
||||
educationLevelList.value = [
|
||||
{ value: '3912', info: '大学本科' },
|
||||
{ value: '3913', info: '硕士研究生' },
|
||||
{ value: '3914', info: '博士研究生' },
|
||||
{ value: '3915', info: '初中毕业' },
|
||||
{ value: '3916', info: '大学毕业' },
|
||||
{ value: '3917', info: '技工学校毕业' },
|
||||
{ value: '3918', info: '职业高中毕业' },
|
||||
{ value: '3919', info: '小学毕业' },
|
||||
{ value: '3920', info: '普通高中毕业' },
|
||||
{ value: '3921', info: '中等专科毕业' }
|
||||
].sort((a, b) => parseInt(a.value) - parseInt(b.value)); // 确保默认选项也按编码排序
|
||||
{ value: '1', info: '大学本科' },
|
||||
{ value: '2', info: '硕士研究生' },
|
||||
{ value: '3', info: '博士研究生' },
|
||||
{ value: '4', info: '初中毕业' },
|
||||
{ value: '5', info: '大学专科结业' },
|
||||
{ value: '6', info: '技工学院结业' },
|
||||
{ value: '7', info: '职业高中结业' },
|
||||
{ value: '8', info: '小学毕业' },
|
||||
{ value: '9', info: '普通高中结业' },
|
||||
{ value: '10', info: '中等专科结业' },
|
||||
{ value: '99', info: '其他' }
|
||||
];
|
||||
}
|
||||
};
|
||||
const options = ref(pcas); // 地区数据
|
||||
@@ -1403,10 +1468,8 @@ const getCountryCodeOptions = async () => {
|
||||
|
||||
// 显示弹框
|
||||
function show() {
|
||||
// 重置为新增模式
|
||||
isEditMode.value = false;
|
||||
title.value = '新增患者';
|
||||
originalFormData.value = {};
|
||||
// 重置表单为初始状态
|
||||
reset();
|
||||
|
||||
// queryParams.roleId = props.roleId;
|
||||
getList();
|
||||
@@ -1452,6 +1515,22 @@ function reset() {
|
||||
busNo: undefined,
|
||||
organizationId: undefined,
|
||||
birthDate: undefined,
|
||||
postalCode: undefined,
|
||||
hukouAddress: undefined,
|
||||
hukouAddressSelect: undefined,
|
||||
hukouAddressProvince: undefined,
|
||||
hukouAddressCity: undefined,
|
||||
hukouAddressDistrict: undefined,
|
||||
hukouAddressStreet: undefined,
|
||||
companyAddress: undefined,
|
||||
patientDerived: undefined,
|
||||
educationLevel: undefined,
|
||||
guardianName: undefined,
|
||||
guardianRelation: undefined,
|
||||
guardianPhone: undefined,
|
||||
guardianIdType: undefined,
|
||||
guardianIdNo: undefined,
|
||||
guardianAddress: undefined,
|
||||
};
|
||||
// 重置编辑模式状态
|
||||
isEditMode.value = false;
|
||||
@@ -1509,6 +1588,18 @@ function submitForm() {
|
||||
if (!form.value.identifierNo) {
|
||||
form.value.typeCode = undefined;
|
||||
}
|
||||
// 修复死亡时间日期格式:确保 yyyy-MM-dd HH:mm:ss 格式
|
||||
if (form.value.deceasedDate) {
|
||||
const d = form.value.deceasedDate;
|
||||
if (d instanceof Date) {
|
||||
const pad = (n) => String(n).padStart(2, '0');
|
||||
form.value.deceasedDate = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + ' ' + pad(d.getHours()) + ':' + pad(d.getMinutes()) + ':' + pad(d.getSeconds());
|
||||
} else if (typeof d === 'string') {
|
||||
// 将任何非标准格式转为 yyyy-MM-dd HH:mm:ss
|
||||
const normalized = d.replace(/\//g, '-').replace(/T/, ' ').replace(/\.\d+Z?$/, '').trim();
|
||||
form.value.deceasedDate = normalized;
|
||||
}
|
||||
}
|
||||
// 拼接完整地址用于提交,但不覆写表单字段(避免弹窗关闭前显示全地址)
|
||||
const submitData = { ...form.value, address: getAddress(form) };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div
|
||||
v-loading="readCardLoading"
|
||||
class="app-container"
|
||||
@@ -122,6 +122,7 @@
|
||||
<patientList
|
||||
:searchkey="patientSearchKey"
|
||||
@selsect-patient="selsectPatient"
|
||||
@mousedown.prevent
|
||||
/>
|
||||
<template #reference>
|
||||
<el-input
|
||||
@@ -2079,10 +2080,20 @@ async function confirmCheckIn() {
|
||||
// 每次开始新的签到流程先清理残留 slotId,避免历史脏值串单
|
||||
currentSlotId.value = null;
|
||||
|
||||
// 防御性校验:确保关键字段存在
|
||||
if (!patient.departmentId) {
|
||||
ElMessage.error('该号源缺少科室信息,无法完成签到,请联系管理员');
|
||||
return;
|
||||
}
|
||||
if (!patient.realPatientId) {
|
||||
ElMessage.error('该号源缺少患者信息,无法完成签到,请联系管理员');
|
||||
return;
|
||||
}
|
||||
|
||||
// 弹出确认提示
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确认为患者【${patient.patientName}】办理签到挂号?\n` +
|
||||
`确认为患者【${patient.patientName || '未知患者'}】办理签到挂号?\n` +
|
||||
`科室:${patient.department || '-'}\n` +
|
||||
`医生:${patient.doctor || '-'}\n` +
|
||||
`费用:¥${patient.fee || '0.00'}`,
|
||||
@@ -2215,7 +2226,7 @@ async function confirmCheckIn() {
|
||||
* 点击患者列表给表单赋值
|
||||
*/
|
||||
function selsectPatient(row) {
|
||||
form.value = { ...form.value, ...row };
|
||||
Object.assign(form.value, row);
|
||||
form.value.patientId = row.id;
|
||||
form.value.searchKey = row.name;
|
||||
form.value.name = row.name;
|
||||
@@ -2225,6 +2236,7 @@ function selsectPatient(row) {
|
||||
form.value.firstEnum_enumText = row.firstEnum_enumText;
|
||||
form.value.age = row.age;
|
||||
form.value.identifierNo = row.identifierNo;
|
||||
showPopover.value = false;
|
||||
}
|
||||
|
||||
// 设置新增参数
|
||||
|
||||
@@ -263,9 +263,8 @@ const handleCurrentChange = (currentRow) => {
|
||||
currentSelectRow.value = currentRow;
|
||||
};
|
||||
|
||||
function clickRow(row, column, cell, event) {
|
||||
// cell-click 事件会传递 row, column, cell, event 四个参数
|
||||
// 确保传递的是完整的行数据
|
||||
function clickRow({ row }) {
|
||||
// vxe-table 4.x cell-click 事件参数是 { row, column, ... } 对象,需解构取 row
|
||||
if (row) {
|
||||
emit('selectAdviceBase', row);
|
||||
}
|
||||
|
||||
@@ -38,170 +38,15 @@
|
||||
max-height="650"
|
||||
:data="prescriptionList"
|
||||
:row-config="{ keyField: 'uniqueKey', expandRowKeys: expandOrder }"
|
||||
:column-config="{ resizable: true }"
|
||||
border
|
||||
auto-resize
|
||||
@cell-dblclick="clickRowDb"
|
||||
>
|
||||
<vxe-column
|
||||
type="expand"
|
||||
width="40"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-form
|
||||
:ref="'formRef' + scope.rowIndex"
|
||||
:model="scope.row"
|
||||
:rules="rowRules"
|
||||
>
|
||||
<div style="padding: 16px; background: #f8f9fa; border-radius: 8px">
|
||||
<!-- 药品类型(adviceType == 1)和耗材类型(adviceType == 2)使用相同的界面 -->
|
||||
<template v-if="scope.row.adviceType == 1 || scope.row.adviceType == 2">
|
||||
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{
|
||||
scope.row.adviceName +
|
||||
' ' +
|
||||
(scope.row.volume ? scope.row.volume + ' ' : '') +
|
||||
(scope.row.unitPrice ? scope.row.unitPrice + ' 元/' : '') +
|
||||
(scope.row.unitCode_dictText || '')
|
||||
}}
|
||||
</span>
|
||||
<div class="form-group">
|
||||
<!-- 库存不为空时显示批号选择 -->
|
||||
<el-select
|
||||
v-if="scope.row.stockList && scope.row.stockList.length > 0"
|
||||
v-model="scope.row.lotNumber"
|
||||
style="width: 180px; margin-right: 20px"
|
||||
placeholder="选择批号"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in scope.row.stockList"
|
||||
:key="item.lotNumber"
|
||||
:value="item.lotNumber"
|
||||
:label="
|
||||
item.locationName +
|
||||
' ' +
|
||||
'批次号: ' +
|
||||
item.lotNumber +
|
||||
' ' +
|
||||
' 库存:' +
|
||||
(item.quantity / scope.row.partPercent).toFixed(2) +
|
||||
item.unitCode_dictText +
|
||||
' 单价:' +
|
||||
item.price.toFixed(2) +
|
||||
'/' +
|
||||
item.unitCode_dictText
|
||||
"
|
||||
@click="handleNumberClick(item, scope.rowIndex)"
|
||||
/>
|
||||
</el-select>
|
||||
<!-- 库存为空时显示提示 -->
|
||||
<span
|
||||
v-else
|
||||
style="color: #EF4444; margin-right: 20px; font-size: 14px;"
|
||||
>
|
||||
无可用库存
|
||||
</span>
|
||||
<el-form-item
|
||||
label="数量:"
|
||||
prop="quantity"
|
||||
class="required-field"
|
||||
data-prop="quantity"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="scope.row.quantity"
|
||||
placeholder="数量"
|
||||
style="width: 70px"
|
||||
controls-position="right"
|
||||
:controls="false"
|
||||
@keyup.enter.prevent="handleEnter('quantity', scope.row, scope.rowIndex)"
|
||||
@input="calculateTotalPrice(scope.row, scope.rowIndex)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-select
|
||||
v-if="scope.row.unitCodeList && scope.row.unitCodeList.length > 0"
|
||||
v-model="scope.row.unitCode"
|
||||
style="width: 70px; margin-right: 20px"
|
||||
placeholder="单位"
|
||||
@change="calculateTotalAmount(scope.row, scope.rowIndex)"
|
||||
>
|
||||
<template
|
||||
v-for="item in scope.row.unitCodeList"
|
||||
:key="item.value"
|
||||
>
|
||||
<el-option
|
||||
v-if="item.type != unitMap['dose']"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
<span class="total-amount">
|
||||
总金额:{{ scope.row.totalPrice ? scope.row.totalPrice + ' 元' : '0.00 元' }}
|
||||
</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSaveSign(scope.row, scope.rowIndex)"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="display: flex; align-items: center; margin-bottom: 16px; gap: 16px">
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{
|
||||
scope.row.adviceName + ' ' + scope.row.unitPrice
|
||||
? Number(scope.row.unitPrice).toFixed(2)
|
||||
: '-' + '元'
|
||||
}}
|
||||
</span>
|
||||
<div class="form-group">
|
||||
<el-form-item
|
||||
label="执行次数:"
|
||||
prop="quantity"
|
||||
class="required-field"
|
||||
data-prop="quantity"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="scope.row.quantity"
|
||||
placeholder="执行次数"
|
||||
style="width: 100px; margin: 0 20px"
|
||||
controls-position="right"
|
||||
:controls="false"
|
||||
@keyup.enter.prevent="handleEnter('quantity', scope.row, scope.rowIndex)"
|
||||
@input="calculateTotalPrice(scope.row, scope.rowIndex)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-tree-select
|
||||
v-model="scope.row.orgId"
|
||||
clearable
|
||||
:data="organization"
|
||||
:props="{ value: 'id', label: 'name', children: 'children' }"
|
||||
value-key="id"
|
||||
check-strictly
|
||||
placeholder="请选择执行科室"
|
||||
style="min-width: 150px; width: auto;"
|
||||
class="org-select"
|
||||
/>
|
||||
<span class="total-amount">
|
||||
总金额:{{ scope.row.totalPrice ? scope.row.totalPrice + ' 元' : '0.00 元' }}
|
||||
</span>
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
<!-- 金额: {{ scope.row.priceList[0].price }} -->
|
||||
</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSaveSign(scope.row, scope.rowIndex)"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
</vxe-column>
|
||||
/>
|
||||
<vxe-column
|
||||
title=""
|
||||
align="center"
|
||||
@@ -370,6 +215,7 @@
|
||||
<vxe-column
|
||||
title="总量"
|
||||
align="center"
|
||||
width="100"
|
||||
field=""
|
||||
>
|
||||
<template #default="scope">
|
||||
@@ -383,6 +229,7 @@
|
||||
align="right"
|
||||
field=""
|
||||
header-align="center"
|
||||
width="130"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span
|
||||
@@ -430,6 +277,151 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
<!-- 编辑表单卡片:独立于表格,选中项目后显示在表格下方 -->
|
||||
<div
|
||||
v-if="editingRow"
|
||||
class="edit-form-card"
|
||||
>
|
||||
<el-form
|
||||
:ref="'editFormRef'"
|
||||
:model="editingRow"
|
||||
:rules="rowRules"
|
||||
>
|
||||
<div style="padding: 16px; background: #f8f9fa; border-radius: 8px">
|
||||
<template v-if="editingRow.adviceType == 1 || editingRow.adviceType == 2">
|
||||
<div style="display: flex; align-items: center; gap: 16px; flex-wrap: wrap">
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{
|
||||
editingRow.adviceName +
|
||||
' ' +
|
||||
(editingRow.volume ? editingRow.volume + ' ' : '') +
|
||||
(editingRow.unitPrice ? editingRow.unitPrice + ' 元/' : '') +
|
||||
(editingRow.unitCode_dictText || '')
|
||||
}}
|
||||
</span>
|
||||
<div class="form-group">
|
||||
<el-select
|
||||
v-if="editingRow.stockList && editingRow.stockList.length > 0"
|
||||
v-model="editingRow.lotNumber"
|
||||
style="width: 180px; margin-right: 20px"
|
||||
placeholder="选择批号"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in editingRow.stockList"
|
||||
:key="item.lotNumber"
|
||||
:value="item.lotNumber"
|
||||
:label="
|
||||
item.locationName +
|
||||
' 批次号: ' + item.lotNumber +
|
||||
' 库存:' + (item.quantity / editingRow.partPercent).toFixed(2) +
|
||||
item.unitCode_dictText +
|
||||
' 单价:' + item.price.toFixed(2) + '/' + item.unitCode_dictText
|
||||
"
|
||||
@click="handleNumberClick(item, editingRowIndex)"
|
||||
/>
|
||||
</el-select>
|
||||
<span
|
||||
v-else
|
||||
style="color: #EF4444; margin-right: 20px; font-size: 14px;"
|
||||
>无可用库存</span>
|
||||
<el-form-item
|
||||
label="数量:"
|
||||
prop="quantity"
|
||||
class="required-field"
|
||||
data-prop="quantity"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="editingRow.quantity"
|
||||
placeholder="数量"
|
||||
style="width: 70px"
|
||||
controls-position="right"
|
||||
:controls="false"
|
||||
@keyup.enter.prevent="handleEnter('quantity', editingRow, editingRowIndex)"
|
||||
@input="calculateTotalPrice(editingRow, editingRowIndex)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-select
|
||||
v-if="editingRow.unitCodeList && editingRow.unitCodeList.length > 0"
|
||||
v-model="editingRow.unitCode"
|
||||
style="width: 70px; margin-right: 20px"
|
||||
placeholder="单位"
|
||||
@change="calculateTotalAmount(editingRow, editingRowIndex)"
|
||||
>
|
||||
<template
|
||||
v-for="item in editingRow.unitCodeList"
|
||||
:key="item.value"
|
||||
>
|
||||
<el-option
|
||||
v-if="item.type != unitMap['dose']"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
<span class="total-amount">
|
||||
总金额:{{ editingRow.totalPrice ? editingRow.totalPrice + ' 元' : '0.00 元' }}
|
||||
</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSaveSign(editingRow, editingRowIndex)"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div style="display: flex; align-items: center; gap: 16px; flex-wrap: wrap">
|
||||
<span style="font-size: 16px; font-weight: 600">
|
||||
{{
|
||||
editingRow.adviceName + ' ' + editingRow.unitPrice
|
||||
? Number(editingRow.unitPrice).toFixed(2)
|
||||
: '-' + '元'
|
||||
}}
|
||||
</span>
|
||||
<div class="form-group">
|
||||
<el-form-item
|
||||
label="执行次数:"
|
||||
prop="quantity"
|
||||
class="required-field"
|
||||
data-prop="quantity"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="editingRow.quantity"
|
||||
placeholder="执行次数"
|
||||
style="width: 100px; margin: 0 20px"
|
||||
controls-position="right"
|
||||
:controls="false"
|
||||
@keyup.enter.prevent="handleEnter('quantity', editingRow, editingRowIndex)"
|
||||
@input="calculateTotalPrice(editingRow, editingRowIndex)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-tree-select
|
||||
v-model="editingRow.orgId"
|
||||
clearable
|
||||
:data="organization"
|
||||
:props="{ value: 'id', label: 'name', children: 'children' }"
|
||||
value-key="id"
|
||||
check-strictly
|
||||
placeholder="请选择执行科室"
|
||||
style="min-width: 150px; width: auto;"
|
||||
class="org-select"
|
||||
/>
|
||||
<span class="total-amount">
|
||||
总金额:{{ editingRow.totalPrice ? editingRow.totalPrice + ' 元' : '0.00 元' }}
|
||||
</span>
|
||||
</div>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSaveSign(editingRow, editingRowIndex)"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -444,7 +436,7 @@ import {
|
||||
getEncounterDiagnosis,
|
||||
} from './api';
|
||||
import adviceBaseList from './adviceBaseList';
|
||||
import {getCurrentInstance, nextTick, ref, watch} from 'vue';
|
||||
import {getCurrentInstance, nextTick, ref, watch, computed} from 'vue';
|
||||
|
||||
const emit = defineEmits(['selectDiagnosis']);
|
||||
const prescriptionList = ref([]);
|
||||
@@ -493,6 +485,14 @@ const isAdding = ref(false);
|
||||
const isSaving = ref(false); // #437 防重复提交锁
|
||||
const prescriptionRef = ref();
|
||||
const expandOrder = ref([]); //目前的展开行
|
||||
const editingRow = computed(() => {
|
||||
if (expandOrder.value.length === 0) return null;
|
||||
return prescriptionList.value.find(r => r.uniqueKey === expandOrder.value[0]) || null;
|
||||
});
|
||||
const editingRowIndex = computed(() => {
|
||||
if (expandOrder.value.length === 0) return -1;
|
||||
return prescriptionList.value.findIndex(r => r.uniqueKey === expandOrder.value[0]);
|
||||
});
|
||||
const stockList = ref([]);
|
||||
const groupList = ref([])
|
||||
const { proxy } = getCurrentInstance();
|
||||
@@ -546,8 +546,11 @@ watch(
|
||||
nextTick(() => {
|
||||
|
||||
const index = prescriptionList.value.findIndex((row) => row.uniqueKey === newValue[0]);
|
||||
const items = proxy.$refs['formRef' + index]?.$el?.querySelectorAll('[data-prop]');
|
||||
requiredProps.value = Array.from(items).map((item) => item.dataset.prop);
|
||||
const formEl = proxy.$refs['editFormRef'];
|
||||
if (formEl) {
|
||||
const items = formEl.$el?.querySelectorAll('[data-prop]') || formEl.querySelectorAll?.('[data-prop]');
|
||||
if (items) requiredProps.value = Array.from(items).map((item) => item.dataset.prop);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
requiredProps.value = {};
|
||||
@@ -831,11 +834,9 @@ async function selectAdviceBase(key, row) {
|
||||
});
|
||||
}
|
||||
|
||||
// 将选中的基础项“覆盖”到当前处方行(这是之前正常工作的核心逻辑)
|
||||
prescriptionList.value[rowIndex.value] = {
|
||||
...prescriptionList.value[rowIndex.value],
|
||||
...JSON.parse(JSON.stringify(row)),
|
||||
};
|
||||
// 将选中的基础项“覆盖”到当前处方行
|
||||
// 用 Object.assign 原地修改,确保 vxe-table 能检测到变更重新渲染
|
||||
Object.assign(prescriptionList.value[rowIndex.value], JSON.parse(JSON.stringify(row)));
|
||||
|
||||
// 后续字段处理保持原样
|
||||
// 🔧 修复执行科室逻辑:诊疗项目优先使用项目维护的所属科室(row.orgId)
|
||||
@@ -1271,7 +1272,7 @@ function handleSaveSign(row, index) {
|
||||
return;
|
||||
}
|
||||
isSaving.value = true; // #437 立即加锁,消除 TOCTOU 竞态
|
||||
proxy.$refs['formRef' + index].validate((valid) => {
|
||||
proxy.$refs['editFormRef'].validate((valid) => {
|
||||
if (!valid) {
|
||||
isSaving.value = false; // 验证失败释放锁
|
||||
return;
|
||||
@@ -1391,6 +1392,14 @@ defineExpose({ getListInfo, closeAllPopovers });
|
||||
:deep(.vxe-table--expand-btn) {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// 编辑表单卡片:独立于表格,显示在表格下方
|
||||
.edit-form-card {
|
||||
margin-top: 12px;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
}
|
||||
.medicine-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div>
|
||||
<el-row :gutter="24">
|
||||
<el-col
|
||||
@@ -873,90 +873,66 @@ function handleInfectiousDiseaseReport() {
|
||||
// 疾病名称到报卡编码的映射(根据传染病报告卡弹窗中的疾病列表)
|
||||
const diseaseNameToCode = {
|
||||
// 甲类
|
||||
'鼠疫': '0101',
|
||||
'霍乱': '0102',
|
||||
'鼠疫': '0101', '霍乱': '0102',
|
||||
// 乙类
|
||||
'传染性非典型肺炎': '0201',
|
||||
'艾滋病': '0202',
|
||||
'病毒性肝炎': '0203',
|
||||
'脊髓灰质炎': '0204',
|
||||
'人感染高致病性禽流感': '0205',
|
||||
'麻疹': '0206',
|
||||
'流行性出血热': '0207',
|
||||
'狂犬病': '0208',
|
||||
'流行性乙型脑炎': '0209',
|
||||
'登革热': '0210',
|
||||
'炭疽': '0211',
|
||||
'细菌性和阿米巴性痢疾': '0212',
|
||||
'肺结核': '0213',
|
||||
'伤寒和副伤寒': '0214',
|
||||
'流行性脑脊髓膜炎': '0215',
|
||||
'百日咳': '0216',
|
||||
'白喉': '0217',
|
||||
'新生儿破伤风': '0218',
|
||||
'猩红热': '0219',
|
||||
'布鲁氏菌病': '0220',
|
||||
'淋病': '0221',
|
||||
'梅毒': '0222',
|
||||
'钩端螺旋体病': '0223',
|
||||
'血吸虫病': '0224',
|
||||
'疟疾': '0225',
|
||||
'新型冠状病毒肺炎': '0226',
|
||||
'甲型H1N1流感': '0227',
|
||||
'传染性非典型肺炎': '0201', '艾滋病': '0202', '病毒性肝炎': '0203',
|
||||
'脊髓灰质炎': '0204', '人感染高致病性禽流感': '0205', '麻疹': '0206',
|
||||
'流行性出血热': '0207', '狂犬病': '0208', '流行性乙型脑炎': '0209',
|
||||
'登革热': '0210', '炭疽': '0211', '细菌性和阿米巴性痢疾': '0212',
|
||||
'肺结核': '0213', '伤寒和副伤寒': '0214', '流行性脑脊髓膜炎': '0215',
|
||||
'百日咳': '0216', '白喉': '0217', '新生儿破伤风': '0218',
|
||||
'猩红热': '0219', '布鲁氏菌病': '0220', '淋病': '0221',
|
||||
'梅毒': '0222', '钩端螺旋体病': '0223', '血吸虫病': '0224',
|
||||
'疟疾': '0225', '新型冠状病毒肺炎': '0226', '甲型H1N1流感': '0227',
|
||||
'人感染H7N9禽流感': '0228',
|
||||
// 丙类
|
||||
'流行性感冒': '0301',
|
||||
'流行性腮腺炎': '0302',
|
||||
'风疹': '0303',
|
||||
'急性出血性结膜炎': '0304',
|
||||
'麻风病': '0305',
|
||||
'流行性和地方性斑疹伤寒': '0306',
|
||||
'黑热病': '0307',
|
||||
'包虫病': '0308',
|
||||
'丝虫病': '0309',
|
||||
'流行性感冒': '0301', '流行性腮腺炎': '0302', '风疹': '0303',
|
||||
'急性出血性结膜炎': '0304', '麻风病': '0305',
|
||||
'流行性和地方性斑疹伤寒': '0306', '黑热病': '0307',
|
||||
'包虫病': '0308', '丝虫病': '0309',
|
||||
'除霍乱/菌痢/伤寒副伤寒以外的感染性腹泻病': '0310',
|
||||
'其它感染性腹泻病': '0310',
|
||||
'手足口病': '0311',
|
||||
'其它感染性腹泻病': '0310', '手足口病': '0311',
|
||||
};
|
||||
|
||||
// 获取所有需要触发传染病报卡的诊断,但跳过已有已提交报卡的诊断
|
||||
// 判断依据:1) 硬编码名称匹配;2) 后端配置了 reportTypeCode(报卡类型)
|
||||
const infectiousDiagnoses = form.value.diagnosisList
|
||||
.map(d => {
|
||||
// 跳过已有已提交报卡的诊断
|
||||
if (d.hasInfectiousReport === 1) return null;
|
||||
// 获取所有需要触发传染病报卡的诊断,跳过已有已提交报卡的诊断
|
||||
const infectiousDiagnoses = [];
|
||||
|
||||
let diseaseCode = null;
|
||||
for (const d of form.value.diagnosisList) {
|
||||
// 跳过已有已提交报卡的诊断
|
||||
if (d.hasInfectiousReport === 1) continue;
|
||||
|
||||
// 1. 尝试精确名称匹配
|
||||
if (d.name && diseaseNameToCode[d.name]) {
|
||||
diseaseCode = diseaseNameToCode[d.name];
|
||||
}
|
||||
// 2. 尝试部分名称匹配(如"古典生物型霍乱"包含"霍乱")
|
||||
else if (d.name && d.reportTypeCode) {
|
||||
const match = Object.entries(diseaseNameToCode).find(([name]) =>
|
||||
name && d.name.includes(name)
|
||||
);
|
||||
if (match) {
|
||||
diseaseCode = match[1];
|
||||
}
|
||||
}
|
||||
// 3. 配置了 reportTypeCode 但无名称匹配,仍触发弹窗(不预选疾病)
|
||||
else if (d.reportTypeCode) {
|
||||
let diseaseCode = null;
|
||||
|
||||
// 1. 精确名称匹配硬编码映射表
|
||||
if (d.name && diseaseNameToCode[d.name]) {
|
||||
diseaseCode = diseaseNameToCode[d.name];
|
||||
}
|
||||
// 2. 部分名称匹配(双向:诊断名包含映射key,或映射key包含诊断名)
|
||||
else if (d.name && d.reportTypeCode) {
|
||||
const match = Object.entries(diseaseNameToCode).find(([name]) =>
|
||||
name && (d.name.includes(name) || name.includes(d.name))
|
||||
);
|
||||
if (match) {
|
||||
diseaseCode = match[1];
|
||||
} else {
|
||||
// 3. 诊断目录中配置了报卡类型(reportTypeCode)但无名称匹配,仍触发弹窗
|
||||
diseaseCode = 'OTHER';
|
||||
}
|
||||
}
|
||||
// 4. 仅有reportTypeCode但name为空
|
||||
else if (d.reportTypeCode) {
|
||||
diseaseCode = 'OTHER';
|
||||
}
|
||||
|
||||
if (!diseaseCode) return null;
|
||||
return { diagnosis: d, diseaseCode };
|
||||
})
|
||||
.filter(item => item !== null);
|
||||
if (diseaseCode) {
|
||||
infectiousDiagnoses.push({ diagnosis: d, diseaseCode });
|
||||
}
|
||||
}
|
||||
|
||||
if (infectiousDiagnoses.length === 0) return;
|
||||
|
||||
const allSelectedDiseases = infectiousDiagnoses.map(item => item.diseaseCode);
|
||||
|
||||
if (allSelectedDiseases.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 优先使用命中传染病映射的主诊断,否则使用第一条命中的传染病诊断
|
||||
const mainInfectiousDiagnosis = infectiousDiagnoses.find(item => item.diagnosis.maindiseFlag === 1)?.diagnosis;
|
||||
const firstInfectiousDiagnosis = infectiousDiagnoses[0].diagnosis;
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
<template #default="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.isUrgent"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
disabled
|
||||
/>
|
||||
@@ -146,7 +146,7 @@
|
||||
<template #default="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.isCharged"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
disabled
|
||||
/>
|
||||
@@ -161,7 +161,7 @@
|
||||
<template #default="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.isRefunded"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
disabled
|
||||
/>
|
||||
@@ -176,7 +176,7 @@
|
||||
<template #default="{ row }">
|
||||
<el-checkbox
|
||||
v-model="row.isExecuted"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
disabled
|
||||
/>
|
||||
@@ -452,14 +452,14 @@
|
||||
<el-form-item label="状态">
|
||||
<el-checkbox
|
||||
v-model="form.isUrgent"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
>
|
||||
急
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="form.isCharged"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
disabled
|
||||
>
|
||||
@@ -467,7 +467,7 @@
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="form.isRefunded"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
disabled
|
||||
>
|
||||
@@ -475,7 +475,7 @@
|
||||
</el-checkbox>
|
||||
<el-checkbox
|
||||
v-model="form.isExecuted"
|
||||
:true-value="true"
|
||||
:true-value="1"
|
||||
:false-value="0"
|
||||
disabled
|
||||
>
|
||||
|
||||
@@ -1750,10 +1750,8 @@ onMounted(() => {
|
||||
createNewPrescription();
|
||||
handleAddPrescription(null, false);
|
||||
}
|
||||
// 默认展开个人:只请求个人组套
|
||||
if (props.patientInfo?.orgId) {
|
||||
fetchOrderGroups('personal');
|
||||
}
|
||||
// 默认展开个人:个人组套不依赖 orgId(使用 practitionerId 查询)
|
||||
fetchOrderGroups('personal');
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
@@ -1802,12 +1800,14 @@ watch(
|
||||
watch(
|
||||
() => props.patientInfo?.orgId,
|
||||
(orgId) => {
|
||||
if (!orgId) return;
|
||||
// 🔧 Bug #730 修复:个人组套不依赖 orgId,只需 practitionerId(登录用户自带)
|
||||
if (!orderGroupLoaded.value.personal) {
|
||||
fetchOrderGroups('personal');
|
||||
}
|
||||
// 预加载医嘱基础数据,提升搜索响应速度
|
||||
preloadAdviceData();
|
||||
if (orgId) {
|
||||
preloadAdviceData();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
@@ -5056,8 +5056,9 @@ async function fetchOrderGroups(scope, { force = false } = {}) {
|
||||
|
||||
const orgId = props.patientInfo?.orgId;
|
||||
console.log('[fetchOrderGroups] orgId:', orgId);
|
||||
if (!orgId) {
|
||||
console.log('[fetchOrderGroups] orgId 为空,返回');
|
||||
// 🔧 Bug #730 修复:个人/科室组套不依赖 orgId,只有全院组套需要 orgId
|
||||
if (scope === 'hospital' && !orgId) {
|
||||
console.log('[fetchOrderGroups] 全院组套需要 orgId 但为空,返回');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,8 @@
|
||||
</el-table>
|
||||
<el-pagination style="margin-top:12px;justify-content:flex-end" v-model:current-page="q.pageNo" v-model:page-size="q.pageSize" :total="total" layout="total,prev,pager,next" @current-change="loadData"/>
|
||||
<el-dialog v-model="addVisible" title="激活绿色通道" width="500px">
|
||||
<el-form :model="addForm" label-width="120px">
|
||||
<el-form-item label="患者ID"><el-input-number v-model="addForm.patientId" :min="1"/></el-form-item>
|
||||
<el-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-width="120px">
|
||||
<el-form-item label="患者ID" prop="patientId"><el-input-number v-model="addForm.patientId" :min="1" style="width:100%"/></el-form-item>
|
||||
<el-form-item label="疾病类型"><el-input v-model="addForm.diseaseType" placeholder="如: 急性心肌梗死、脑卒中"/></el-form-item>
|
||||
<el-form-item label="目标时间(min)"><el-input-number v-model="addForm.targetTime" :min="1"/></el-form-item>
|
||||
<el-form-item label="医生"><el-input v-model="addForm.doctor"/></el-form-item>
|
||||
@@ -76,13 +76,15 @@ import {getPage,activate,complete,getStats,del} from './api'
|
||||
const tableData=ref([]);const total=ref(0);const stats=ref({})
|
||||
const addVisible=ref(false);const completeVisible=ref(false)
|
||||
const addForm=ref({patientId:null,diseaseType:'',targetTime:90,doctor:''})
|
||||
const addFormRef=ref(null)
|
||||
const addFormRules={patientId:[{required:true,message:'请选择患者',trigger:'blur'}]}
|
||||
const completeForm=ref({doorToTreatmentTime:60});let currentId=null
|
||||
const q=ref({pageNo:1,pageSize:20,diseaseType:'',isAchieved:null})
|
||||
const loadData=async()=>{const r=await getPage(q.value);tableData.value=r.data?.records||[];total.value=r.data?.total||0}
|
||||
const refreshStats=async()=>{const r=await getStats({});stats.value=r.data||{}}
|
||||
const showAdd=()=>{addForm.value={patientId:null,diseaseType:'',targetTime:90,doctor:''};addVisible.value=true}
|
||||
const showComplete=(row)=>{currentId=row.id;completeForm.value={doorToTreatmentTime:60};completeVisible.value=true}
|
||||
const submitAdd=async()=>{await activate(addForm.value);ElMessage.success('绿色通道已激活');addVisible.value=false;loadData();refreshStats()}
|
||||
const submitAdd=async()=>{if(addFormRef.value){try{await addFormRef.value.validate()}catch{return}}await activate(addForm.value);ElMessage.success('绿色通道已激活');addVisible.value=false;loadData();refreshStats()}
|
||||
const doComplete=async()=>{await complete(currentId,completeForm.value);ElMessage.success('评估完成');completeVisible.value=false;loadData();refreshStats()}
|
||||
const delItem=async(id)=>{await del(id);ElMessage.success('已删除');loadData();refreshStats()}
|
||||
onMounted(()=>{loadData();refreshStats()})
|
||||
|
||||
@@ -18,17 +18,13 @@
|
||||
查询
|
||||
</el-button>
|
||||
</el-space>
|
||||
<el-space>
|
||||
<!-- <el-button>读卡</el-button> -->
|
||||
<!-- <el-button type="primary">无档登记</el-button> -->
|
||||
</el-space>
|
||||
</div>
|
||||
<div class="table-container">
|
||||
<vxe-table
|
||||
:data="treatHospitalizedData"
|
||||
style="width: 100%"
|
||||
height="100%"
|
||||
show-overflow
|
||||
show-overflow="title"
|
||||
>
|
||||
<vxe-column
|
||||
type="seq"
|
||||
@@ -104,20 +100,68 @@
|
||||
align="center"
|
||||
title="登记员"
|
||||
/>
|
||||
<vxe-column
|
||||
align="center"
|
||||
title="登记状态"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span :style="{ color: scope.row.statusEnum == 8 ? '#F56C6C' : '#67C23A' }">
|
||||
{{ scope.row.statusEnum == 8 ? '已作废' : '已登记' }}
|
||||
</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
fixed="right"
|
||||
align="center"
|
||||
title="操作"
|
||||
width="88"
|
||||
width="280"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
@click="doEdit(scope.row)"
|
||||
@click="doView(scope.row)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
<el-tooltip
|
||||
v-if="scope.row.statusEnum == 5"
|
||||
content="患者已入科接收,无法修改登记信息"
|
||||
placement="top"
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
text
|
||||
disabled
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-button
|
||||
v-else-if="scope.row.statusEnum == 8"
|
||||
type="primary"
|
||||
text
|
||||
disabled
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
text
|
||||
@click="doModify(scope.row)"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
text
|
||||
:disabled="scope.row.statusEnum == 5 || scope.row.statusEnum == 8"
|
||||
@click="doVoid(scope.row)"
|
||||
>
|
||||
作废
|
||||
</el-button>
|
||||
</template>
|
||||
</vxe-column>
|
||||
</vxe-table>
|
||||
@@ -134,35 +178,32 @@
|
||||
v-model:dialog-visible="patientRegisterVisible"
|
||||
:patient-info="patient"
|
||||
:in-hospital-info="inHospitalInfo"
|
||||
title="登记"
|
||||
:title="dialogTitle"
|
||||
:registration-type="registrationType"
|
||||
:already-edit="alreadyEdit"
|
||||
:no-file="noFile"
|
||||
:is-registered="true"
|
||||
:is-registered="!isEditMode"
|
||||
:is-edit-mode="isEditMode"
|
||||
@ok-act="patientRegisterOK"
|
||||
@cancel-act="cancelAct"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import PatientRegister from './patientRegister.vue';
|
||||
import {getAdmissionPage, getContractList, getInHospitalInfo, getPatientBasicInfo} from './api';
|
||||
import {ElMessage, ElMessageBox} from 'element-plus';
|
||||
import {getAdmissionPage, getContractList, getInHospitalInfo, getPatientBasicInfo, voidRegistration} from './api';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { admit_source_code } = proxy.useDict('admit_source_code');
|
||||
//const { proxy } = getCurrentInstance();
|
||||
const emits = defineEmits([]);
|
||||
// const props = defineProps({});
|
||||
const searchForm = reactive({
|
||||
searchType: 'name',
|
||||
searchKey: '',
|
||||
});
|
||||
const total = ref();
|
||||
const inHospitalInfo = ref({});
|
||||
const alreadyEdit = ref(true);
|
||||
const isEditMode = ref(false);
|
||||
const dialogTitle = ref('登记');
|
||||
const queryParams = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined,
|
||||
registeredFlag: '1',
|
||||
searchKey: '',
|
||||
});
|
||||
@@ -173,22 +214,58 @@ const noFile = ref(false);
|
||||
const registrationType = ref(true);
|
||||
const patient = ref({});
|
||||
const priceTypeList = ref({});
|
||||
const doEdit = (row) => {
|
||||
getPatientBasicInfo(row.patientId).then((res) => {
|
||||
patient.value = res.data;
|
||||
});
|
||||
getInHospitalInfo(row.encounterId).then((res) => {
|
||||
inHospitalInfo.value = res.data;
|
||||
patientRegisterVisible.value = true;
|
||||
noFile.value = false;
|
||||
});
|
||||
const doView = async (row) => {
|
||||
isEditMode.value = false;
|
||||
dialogTitle.value = '查看';
|
||||
const [patientRes, hospitalRes] = await Promise.all([
|
||||
getPatientBasicInfo(row.patientId),
|
||||
getInHospitalInfo(row.encounterId),
|
||||
]);
|
||||
patient.value = patientRes.data;
|
||||
inHospitalInfo.value = hospitalRes.data;
|
||||
patientRegisterVisible.value = true;
|
||||
noFile.value = false;
|
||||
};
|
||||
|
||||
const doModify = async (row) => {
|
||||
isEditMode.value = true;
|
||||
dialogTitle.value = '修改登记';
|
||||
const [patientRes, hospitalRes] = await Promise.all([
|
||||
getPatientBasicInfo(row.patientId),
|
||||
getInHospitalInfo(row.encounterId),
|
||||
]);
|
||||
patient.value = patientRes.data;
|
||||
inHospitalInfo.value = hospitalRes.data;
|
||||
patientRegisterVisible.value = true;
|
||||
noFile.value = false;
|
||||
};
|
||||
|
||||
const doVoid = (row) => {
|
||||
ElMessageBox.confirm(
|
||||
'确认作废该患者的住院登记信息吗?作废后不可撤销',
|
||||
'作废确认',
|
||||
{
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
voidRegistration(row.encounterId).then((res) => {
|
||||
if (res.code == 200) {
|
||||
ElMessage.success('作废成功');
|
||||
getList();
|
||||
} else {
|
||||
ElMessage.error(res.msg || '作废失败');
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
onBeforeMount(() => {});
|
||||
getContract();
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
const activeName = ref('first');
|
||||
|
||||
const patientRegisterOK = () => {
|
||||
patientRegisterVisible.value = false;
|
||||
@@ -211,7 +288,6 @@ function resetQuery() {
|
||||
queryParams.value = {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
searchKey: undefined,
|
||||
registeredFlag: '1',
|
||||
searchKey: '',
|
||||
};
|
||||
@@ -262,7 +338,6 @@ const getList = () => {
|
||||
}
|
||||
|
||||
treatHospitalizedData.value = dataList;
|
||||
// treatHospitalizedData.value = res.data.records;
|
||||
total.value = res.data.total;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -132,6 +132,23 @@ export function registerInHospital(data) {
|
||||
});
|
||||
}
|
||||
|
||||
// 修改住院登记
|
||||
export function updateRegistration(data) {
|
||||
return request({
|
||||
url: '/inhospital-charge/register/update-registration',
|
||||
method: 'put',
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
|
||||
// 作废住院登记
|
||||
export function voidRegistration(encounterId) {
|
||||
return request({
|
||||
url: `/inhospital-charge/register/void-registration?encounterId=${encounterId}`,
|
||||
method: 'put',
|
||||
});
|
||||
}
|
||||
|
||||
// 无档登记
|
||||
export function noFilesRegister(data) {
|
||||
return request({
|
||||
|
||||
@@ -39,7 +39,10 @@
|
||||
/>
|
||||
</el-scrollbar>
|
||||
<template #footer>
|
||||
<div class="advance-container">
|
||||
<div
|
||||
v-if="!props.isEditMode"
|
||||
class="advance-container"
|
||||
>
|
||||
<div
|
||||
v-if="currentFeeType !== 'hipCash'"
|
||||
class="payment-item"
|
||||
@@ -110,13 +113,21 @@
|
||||
取消
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!props.isRegistered"
|
||||
v-if="!props.isRegistered && !props.isEditMode"
|
||||
size="fixed"
|
||||
type="primary"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
登记
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="props.isEditMode"
|
||||
size="fixed"
|
||||
type="primary"
|
||||
@click="handleEditSubmit"
|
||||
>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -125,7 +136,7 @@ const { proxy } = getCurrentInstance();
|
||||
import {ElMessage, ElMessageBox} from 'element-plus';
|
||||
import PatientInfoComp from './patientInfo.vue';
|
||||
import RegisterForm from './registerForm.vue';
|
||||
import {noFilesRegister, registerInHospital} from './api';
|
||||
import {noFilesRegister, registerInHospital, updateRegistration} from './api';
|
||||
import {getInit} from '@/views/doctorstation/components/api';
|
||||
import {useRouter} from 'vue-router';
|
||||
import {wxPay, WxPayResult} from '../../../../charge/cliniccharge/components/api';
|
||||
@@ -161,6 +172,10 @@ const props = defineProps({
|
||||
type: Boolean,
|
||||
default: false, // false 表示待登记,true 表示已登记
|
||||
},
|
||||
isEditMode: {
|
||||
type: Boolean,
|
||||
default: false, // true 表示修改已登记的记录
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
@@ -283,6 +298,7 @@ const handleSubmit = () => {
|
||||
ElMessage.success(res.msg);
|
||||
// 打印预交金收据
|
||||
printDepositReceipt(props.patientInfo, params.inHospitalInfo);
|
||||
emits('okAct');
|
||||
cancelAct();
|
||||
// 询问是否需要医保登记
|
||||
// ElMessageBox.confirm('是否需要进行医保登记?', '医保登记确认', {
|
||||
@@ -392,19 +408,25 @@ const handleSubmit = () => {
|
||||
})
|
||||
.then(() => {
|
||||
console.log('路由跳转成功');
|
||||
emits('okAct');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('路由跳转失败:', error);
|
||||
ElMessage.error('跳转到医保登记页面失败');
|
||||
emits('okAct');
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('跳转异常:', error);
|
||||
emits('okAct');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// 用户取消医保登记,关闭当前弹窗
|
||||
emits('okAct');
|
||||
});
|
||||
} else {
|
||||
// 自费患者,直接通知刷新列表
|
||||
emits('okAct');
|
||||
}
|
||||
cancelAct();
|
||||
} else {
|
||||
@@ -430,6 +452,34 @@ const handleSubmit = () => {
|
||||
}
|
||||
};
|
||||
|
||||
/* 修改登记 */
|
||||
const handleEditSubmit = () => {
|
||||
RegisterFormRef.value.validateData(async () => {
|
||||
const formData = RegisterFormRef.value.submitForm;
|
||||
const params = {
|
||||
encounterId: props.inHospitalInfo.encounterId,
|
||||
patientId: props.patientInfo.patientId,
|
||||
inHospitalOrgId: formData.inHospitalOrgId,
|
||||
wardLocationId: formData.wardLocationId,
|
||||
priorityEnum: formData.priorityEnum,
|
||||
admitSourceCode: formData.admitSourceCode,
|
||||
inWayCode: formData.inWayCode,
|
||||
startTime: formData.startTime,
|
||||
contractNo: formData.contractNo,
|
||||
typeCoce: formData.typeCoce,
|
||||
};
|
||||
updateRegistration(params).then((res) => {
|
||||
if (res.code == 200) {
|
||||
ElMessage.success(res.msg);
|
||||
emits('okAct');
|
||||
cancelAct();
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const openAct = () => {
|
||||
console.log(props.patientInfo, 'patientRegister.vue');
|
||||
console.log(props.inHospitalInfo, 'inHospitalInfo.vue');
|
||||
|
||||
@@ -364,7 +364,7 @@ const medicalInsuranceTitle = ref('');
|
||||
// });
|
||||
const getProvincesAndCitiesInfo = async () => {
|
||||
try {
|
||||
if (inHospitalInfo.encounterId) {
|
||||
if (props.inHospitalInfo.encounterId) {
|
||||
const res = await getProvincesAndCities(props.inHospitalInfo.encounterId);
|
||||
// console.log('获取省市医保字符串', res);
|
||||
if (res && res.code == 200) {
|
||||
@@ -388,8 +388,7 @@ watch(
|
||||
if (newEncounterId) {
|
||||
getProvincesAndCitiesInfo();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
}
|
||||
);
|
||||
|
||||
/* 提交表单 */
|
||||
@@ -463,8 +462,8 @@ watch(
|
||||
}
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
getInitOptions();
|
||||
onMounted(async () => {
|
||||
await getInitOptions();
|
||||
setValue();
|
||||
setDefaultAdmitSource();
|
||||
if (submitForm.inHospitalOrgId) {
|
||||
@@ -505,7 +504,7 @@ function getInitOptions() {
|
||||
// 获取所有病区
|
||||
const wardPromise = getPractitionerWard();
|
||||
|
||||
Promise.all([orgPromise, wardPromise]).then(([orgRes, wardRes]) => {
|
||||
const initPromise = Promise.all([orgPromise, wardPromise]).then(([orgRes, wardRes]) => {
|
||||
// 入院科室:展示所有 typeEnum=2(科室) + classEnum含"2"(住院) 的科室
|
||||
organization.value = orgRes.data.records.filter(
|
||||
(record) => record.typeEnum === 2 && checkClassEnumValue(record.classEnum, 2)
|
||||
@@ -529,19 +528,15 @@ function getInitOptions() {
|
||||
}
|
||||
});
|
||||
|
||||
// if (!props.noFile) {
|
||||
// wardList().then((res) => {
|
||||
// wardListOptions.value = res.data;
|
||||
// });
|
||||
// }
|
||||
diagnosisInit().then((res) => {
|
||||
verificationStatusOptions.value = res.data.verificationStatusOptions;
|
||||
});
|
||||
getContractList().then((response) => {
|
||||
contractList.value = response.data;
|
||||
setValue();
|
||||
});
|
||||
getDiagnosisInfo(undefined);
|
||||
|
||||
return initPromise;
|
||||
}
|
||||
function getDiagnosisInfo(value) {
|
||||
getDiagnosisDefinitionList({ pageSize: 500, pageNo: 1, searchKey: value }).then((res) => {
|
||||
@@ -550,6 +545,7 @@ function getDiagnosisInfo(value) {
|
||||
}
|
||||
|
||||
function handleNodeClick(orgInfo) {
|
||||
const savedWardId = props.inHospitalInfo?.wardLocationId; // 保存原始病区ID,用于编辑模式恢复
|
||||
submitForm.wardLocationId = undefined; // 切换科室时,先清空原有病区
|
||||
submitForm.totalBedsNum = undefined;
|
||||
submitForm.idleBedsNum = undefined;
|
||||
@@ -558,13 +554,20 @@ function handleNodeClick(orgInfo) {
|
||||
wardList({ orgId: orgInfo.id })
|
||||
.then((res) => {
|
||||
wardListOptions.value = res.data || [];
|
||||
if (wardListOptions.value.length > 0 && !props.inHospitalInfo.wardLocationId) {
|
||||
submitForm.wardLocationId = wardListOptions.value[0].id;
|
||||
const defaultWard = wardListOptions.value.find(
|
||||
(item) => item.id === submitForm.wardLocationId
|
||||
);
|
||||
if (defaultWard) {
|
||||
handleWardClick(defaultWard);
|
||||
if (wardListOptions.value.length > 0) {
|
||||
// 编辑模式:尝试恢复之前保存的病区
|
||||
if (savedWardId) {
|
||||
const savedWard = wardListOptions.value.find((item) => String(item.id) === String(savedWardId));
|
||||
if (savedWard) {
|
||||
submitForm.wardLocationId = savedWardId;
|
||||
handleWardClick(savedWard);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 新增模式 或 原病区不在新科室下:自动选中第一个病区
|
||||
if (!submitForm.wardLocationId) {
|
||||
submitForm.wardLocationId = wardListOptions.value[0].id;
|
||||
handleWardClick(wardListOptions.value[0]);
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -619,6 +622,19 @@ function setValue() {
|
||||
submitForm.inWayCode_dictText = props.inHospitalInfo?.inWayCode_dictText;
|
||||
}
|
||||
|
||||
// 编辑模式下,API 数据异步到达后重新赋值表单字段并加载病区
|
||||
watch(
|
||||
() => props.inHospitalInfo.encounterId,
|
||||
(newEncounterId, oldEncounterId) => {
|
||||
if (newEncounterId && newEncounterId !== oldEncounterId) {
|
||||
setValue();
|
||||
if (submitForm.inHospitalOrgId) {
|
||||
handleNodeClick({ id: submitForm.inHospitalOrgId });
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const registerRef = ref();
|
||||
/* 登记 */
|
||||
const validateData = async (callback) => {
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
currentDetail.createTime || '-'
|
||||
}}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="处方号">
|
||||
<el-descriptions-item label="手术单号">
|
||||
{{
|
||||
currentDetail.prescriptionNo || '-'
|
||||
}}
|
||||
@@ -574,6 +574,7 @@ const handleEdit = async (row) => {
|
||||
editFormRef.value?.getLocationInfo?.();
|
||||
editFormRef.value?.getDiagnosisList?.();
|
||||
editFormRef.value?.loadDoctorOptions?.();
|
||||
await editFormRef.value?.getList?.();
|
||||
if (row.requestFormDetailList?.length > 0) {
|
||||
editFormRef.value?.fillForm?.(
|
||||
JSON.parse(row.descJson || '{}'),
|
||||
|
||||
@@ -420,7 +420,7 @@ const getList = async (key) => {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
getSurgeryPage({
|
||||
return getSurgeryPage({
|
||||
pageSize: 1000,
|
||||
keyword: key || undefined,
|
||||
})
|
||||
|
||||
@@ -97,6 +97,7 @@ import {transferOrganization} from './api.js';
|
||||
import {getOrgList, getWardList} from '@/api/public.js';
|
||||
import {patientInfo} from '../../../store/patient.js';
|
||||
|
||||
const emit = defineEmits(['success']);
|
||||
const { proxy } = getCurrentInstance();
|
||||
const dialogVisible = ref(false);
|
||||
const deptList = ref([]); // 科室列表
|
||||
@@ -151,6 +152,7 @@ function submitApplicationForm() {
|
||||
if (res.code == 200) {
|
||||
proxy.$modal.msgSuccess('转科申请已提交');
|
||||
dialogVisible.value = false;
|
||||
emit('success');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -142,9 +142,9 @@
|
||||
</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="开嘱医生" align="center" field="createdStaffName" width="120">
|
||||
<vxe-column title="开嘱医生" align="center" field="requesterId_dictText" width="120">
|
||||
<template #default="scope">
|
||||
{{ scope.row.createdStaffName || '-' }}
|
||||
{{ scope.row.requesterId_dictText || '-' }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="开始时间" align="center" field="startTime" width="200">
|
||||
@@ -396,7 +396,7 @@
|
||||
:encounter-diagnosis-id="encounterDiagnosisId"
|
||||
@success="handleLeaveHospitalSuccess"
|
||||
/>
|
||||
<TransferOrganizationDialog ref="transferOrganizationRef" />
|
||||
<TransferOrganizationDialog ref="transferOrganizationRef" @success="handleTransferOrgSuccess" />
|
||||
</div>
|
||||
<!-- <el-drawer v-model="openDrawer" size="100%">
|
||||
<template #default>
|
||||
@@ -991,6 +991,10 @@ function clickRowDb({ row, column, event }) {
|
||||
prescriptionList.value[index] = row;
|
||||
}
|
||||
expandOrder.value = [row.uniqueKey];
|
||||
// VXE Table v4: clearRowExpand 后 expandRowKeys 不再自动响应,需手动调 API 展开
|
||||
if (prescriptionRef.value?.setRowExpand) {
|
||||
prescriptionRef.value.setRowExpand([row], true);
|
||||
}
|
||||
} else {
|
||||
proxy.$modal.msgWarning('仅待保存或待签发医嘱允许编辑');
|
||||
}
|
||||
@@ -1691,6 +1695,7 @@ function handleSaveSign(row, index) {
|
||||
const originalAdviceType = row.adviceType;
|
||||
if (row.adviceType == 7) {
|
||||
row.adviceType = 1;
|
||||
row.prescriptionCategory = 3; // 出院带药标记,与 handleSaveBatch/handleSave 保持一致
|
||||
}
|
||||
row.conditionId = conditionId.value;
|
||||
// 处理总量为小单位情况,需要把单价也保存成小单位的
|
||||
@@ -1717,6 +1722,10 @@ function handleSaveSign(row, index) {
|
||||
: 0;
|
||||
row.skinTestFlag_enumText = row.skinTestFlag == 1 ? '是' : '否';
|
||||
row.contentJson = JSON.stringify(row);
|
||||
// Bug #589: contentJson 已序列化(含 adviceType=1),恢复内存中的出院带药类型显示
|
||||
if (originalAdviceType == 7) {
|
||||
row.adviceType = 7;
|
||||
}
|
||||
if (row.requestId) {
|
||||
row.dbOpType = '2';
|
||||
savePrescription({ regAdviceSaveList: [row] }).then((res) => {
|
||||
@@ -1882,6 +1891,8 @@ function setValue(row) {
|
||||
...prevRow,
|
||||
...baseRow,
|
||||
uniqueKey: currentUniqueKey, // 确保 uniqueKey 不被覆盖
|
||||
// Bug #589: 出院带药在 baseRow 中被药品的 adviceType=1 覆盖,此处恢复
|
||||
adviceType: prevRow.dischargeFlag ? 7 : baseRow.adviceType,
|
||||
// 🔧 修复执行科室逻辑:
|
||||
// 1. 非诊疗类型(adviceType!=3)不需要执行科室,设为undefined
|
||||
// 2. 诊疗类型优先使用项目维护的所属科室(row.orgId),其次positionId
|
||||
@@ -2806,6 +2817,9 @@ function handleLeaveHospitalSuccess() {
|
||||
function handleTransferOrg() {
|
||||
proxy.$refs['transferOrganizationRef'].openDialog();
|
||||
}
|
||||
function handleTransferOrgSuccess() {
|
||||
getListInfo(false);
|
||||
}
|
||||
|
||||
// 校验每个组号数量是否大于5和对应分组金额是否大于500
|
||||
function validateGroups(saveList) {
|
||||
|
||||
@@ -161,7 +161,7 @@
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="领药时间"
|
||||
title="执行时间"
|
||||
field="times"
|
||||
>
|
||||
<template #default="scope">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<template>
|
||||
<template>
|
||||
<div class="transfer-out-container">
|
||||
<!-- 顶部搜索区域 -->
|
||||
<div>
|
||||
@@ -271,9 +271,14 @@
|
||||
</span>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="医嘱状态" align="center" width="120">
|
||||
<template #default="scope">
|
||||
{{ scope.row.requestStatus_enumText || '-' }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="执行科室" align="center" min-width="120">
|
||||
<template #default="scope">
|
||||
{{ scope.row.orgName || '-' }}
|
||||
{{ scope.row.positionName || scope.row.orgName || '-' }}
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column title="开始时间" width="180">
|
||||
@@ -1109,8 +1114,8 @@ defineExpose({ refreshTap });
|
||||
width: 120px !important;
|
||||
}
|
||||
|
||||
:deep(.vxe-table--header th:nth-child(5)),
|
||||
:deep(.vxe-table--header th:nth-child(6)) {
|
||||
:deep(.vxe-table--header th:nth-child(7)),
|
||||
:deep(.vxe-table--header th:nth-child(8)) {
|
||||
width: 180px !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<template>
|
||||
<div style="height: calc(100vh - 126px)">
|
||||
<div style="height: calc(100vh - 126px); display: flex; flex-direction: column; overflow: hidden">
|
||||
<div
|
||||
style="
|
||||
height: 51px;
|
||||
border-bottom: 2px solid #e4e7ed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
"
|
||||
>
|
||||
<div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; flex-shrink: 1; min-width: 0;">
|
||||
<el-radio-group
|
||||
v-model="type"
|
||||
class="ml20"
|
||||
@change="handleRadioChange"
|
||||
>
|
||||
<el-radio :value="null">
|
||||
<el-radio :value="0">
|
||||
全部
|
||||
</el-radio>
|
||||
<el-radio :value="1">
|
||||
@@ -25,8 +26,15 @@
|
||||
临时
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<el-date-picker
|
||||
v-model="deadline"
|
||||
type="datetime"
|
||||
placeholder="选择截止时间"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 200px"
|
||||
/>
|
||||
<el-button
|
||||
class="ml20"
|
||||
type="primary"
|
||||
plain
|
||||
@click="handleGetPrescription"
|
||||
@@ -34,21 +42,20 @@
|
||||
查询
|
||||
</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<span class="descriptions-item-label">全选:</span>
|
||||
<div style="flex: 1; min-width: 0;"></div>
|
||||
<div style="display: flex; align-items: center; gap: 12px; flex-shrink: 1; min-width: 0;">
|
||||
<span class="descriptions-item-label" style="flex-shrink: 0;">全选:</span>
|
||||
<el-switch
|
||||
v-model="chooseAll"
|
||||
@change="handelSwitchChange"
|
||||
/>
|
||||
<el-button
|
||||
class="ml20"
|
||||
type="primary"
|
||||
@click="handleCheck"
|
||||
>
|
||||
核对通过
|
||||
</el-button>
|
||||
<el-button
|
||||
class="ml20 mr20"
|
||||
type="danger"
|
||||
:disabled="hasDispensedSelected"
|
||||
@click="handleCancel"
|
||||
@@ -59,7 +66,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-loading="loading"
|
||||
style="padding: 10px; background-color: #eef9fd; height: 100%; overflow-y: auto"
|
||||
style="padding: 10px; background-color: #eef9fd; flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden"
|
||||
>
|
||||
<el-collapse
|
||||
v-if="prescriptionList.length > 0"
|
||||
@@ -69,8 +76,6 @@
|
||||
border-bottom: 0px;
|
||||
border-top: 0px;
|
||||
border-radius: 0px;
|
||||
overflow-y: auto;
|
||||
max-height: calc(100vh - 200px);
|
||||
"
|
||||
>
|
||||
<el-collapse-item
|
||||
@@ -81,12 +86,11 @@
|
||||
border: 2px solid #e4e7ed;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 10px;
|
||||
overflow: hidden;
|
||||
"
|
||||
>
|
||||
<template #title>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center">
|
||||
<div>
|
||||
<div style="display: flex; gap: 16px; align-items: center; width: 100%; min-width: 0; overflow: hidden">
|
||||
<div style="flex: 1; min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; padding-right: 12px;">
|
||||
<span>{{ item[0].bedName + '【' + item[0].busNo + '】' }}</span>
|
||||
<span>
|
||||
{{
|
||||
@@ -103,17 +107,18 @@
|
||||
<div
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
margin-right: 20px;
|
||||
flex-shrink: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
"
|
||||
>
|
||||
<div style="display: inline-block; margin-right: 10px">
|
||||
<div style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;">
|
||||
<span class="descriptions-item-label">住院医生:</span>
|
||||
<span>{{ item[0].requesterId_dictText }}</span>
|
||||
</div>
|
||||
<div style="display: inline-block; margin-right: 10px">
|
||||
<div style="white-space: nowrap; flex-shrink: 0;">
|
||||
<div
|
||||
class="descriptions-item-label"
|
||||
style="height: 20px; line-height: 20px; text-align: center; margin: 0"
|
||||
@@ -135,6 +140,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div style="overflow-x: auto">
|
||||
<vxe-table
|
||||
:ref="'tableRef' + index"
|
||||
:data="item"
|
||||
@@ -168,6 +174,7 @@
|
||||
<vxe-column
|
||||
title="医嘱内容"
|
||||
field="adviceName"
|
||||
min-width="220"
|
||||
>
|
||||
<template #default="scope">
|
||||
<span>
|
||||
@@ -217,7 +224,88 @@
|
||||
field="requestTime"
|
||||
width="230"
|
||||
/>
|
||||
<vxe-column
|
||||
title="开始时间"
|
||||
field="startTime"
|
||||
width="150"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
title="单次剂量"
|
||||
field="singleDose"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
title="总量"
|
||||
field="totalAmount"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
title="频次/用法"
|
||||
field="frequencyUsage"
|
||||
width="110"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
title="皮试"
|
||||
field="skinTestStatus"
|
||||
width="90"
|
||||
align="center"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
v-if="scope.row.skinTestStatus"
|
||||
:type="scope.row.skinTestHighlight ? 'danger' : 'info'"
|
||||
:class="{ 'skin-test-warning': scope.row.skinTestHighlight }"
|
||||
size="small"
|
||||
>
|
||||
{{ scope.row.skinTestStatus }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="注射药品"
|
||||
field="isInjection"
|
||||
width="90"
|
||||
align="center"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
v-if="scope.row.isInjection"
|
||||
type="warning"
|
||||
size="small"
|
||||
>
|
||||
注射
|
||||
</el-tag>
|
||||
</template>
|
||||
</vxe-column>
|
||||
<vxe-column
|
||||
title="开嘱医生"
|
||||
field="orderingDoctor"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
title="诊断"
|
||||
field="diagnosis"
|
||||
min-width="150"
|
||||
/>
|
||||
<vxe-column
|
||||
title="停嘱时间"
|
||||
field="stopTime"
|
||||
width="150"
|
||||
align="center"
|
||||
/>
|
||||
<vxe-column
|
||||
title="停嘱医生"
|
||||
field="stopperName"
|
||||
width="100"
|
||||
align="center"
|
||||
/>
|
||||
</vxe-table>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
<el-empty
|
||||
@@ -256,7 +344,7 @@ import {RequestStatus} from '@/utils/medicalConstants';
|
||||
const activeNames = ref([]);
|
||||
const prescriptionList = ref([]);
|
||||
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
|
||||
const type = ref(null);
|
||||
const type = ref(0);
|
||||
const backReasonVisible = ref(false);
|
||||
const backReasonForm = ref({ reason: '' });
|
||||
const backReasonFormRef = ref(null);
|
||||
@@ -355,7 +443,8 @@ function handleGetPrescription() {
|
||||
getPrescriptionList({
|
||||
encounterIds: encounterIds,
|
||||
requestStatus: props.requestStatus,
|
||||
...(type.value != null ? { therapyEnum: type.value } : {}),
|
||||
...(type.value !== 0 ? { therapyEnum: type.value } : {}),
|
||||
...(deadline.value ? { deadline: deadline.value } : {}),
|
||||
pageSize: 10000,
|
||||
pageNo: 1,
|
||||
}).then((res) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div style="display: flex; justify-content: space-between">
|
||||
<div style="width: 20%; height: 90vh; border-right: solid 2px #e4e7ed">
|
||||
<div style="display: flex; height: 90vh; overflow: hidden">
|
||||
<div style="width: 20%; flex-shrink: 0; border-right: solid 2px #e4e7ed; overflow: hidden">
|
||||
<div
|
||||
style="
|
||||
height: 40px;
|
||||
@@ -37,7 +37,7 @@
|
||||
-->
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div style="width: 100%">
|
||||
<div style="flex: 1; min-width: 0; overflow: hidden">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
class="centered-tabs"
|
||||
|
||||
@@ -10,5 +10,5 @@ export function addReport(d){return request({url:'/reconstruction/report/add',me
|
||||
export function submitReport(id){return request({url:'/reconstruction/report/submit/'+id,method:'put'})}
|
||||
export function verifyReport(id,doctor){return request({url:'/reconstruction/report/verify/'+id,method:'put',params:{doctor}})}
|
||||
export function getStats(){return request({url:'/reconstruction/stats',method:'get'})}
|
||||
// 获取医生列表(有医生角色的用户)
|
||||
export function getDoctorList(){return request({url:'/system/user/list',method:'get',params:{pageSize:200}})}
|
||||
// Get all active users for doctor selection
|
||||
export function getDoctorList(){return request({url:'/system/user/list',method:'get',params:{status:'0',pageSize:200}})}
|
||||
|
||||
@@ -230,7 +230,9 @@ function init(){
|
||||
|
||||
// Generate volume
|
||||
const volData=genVolume()
|
||||
const volTex=new THREE.DataTexture(volData,SZ,SZ,SZ,THREE.RedFormat,THREE.FloatType)
|
||||
const volTex=new THREE.Data3DTexture(volData,SZ,SZ,SZ)
|
||||
volTex.format=THREE.RedFormat
|
||||
volTex.type=THREE.FloatType
|
||||
volTex.needsUpdate=true
|
||||
volTex.minFilter=THREE.LinearFilter
|
||||
volTex.magFilter=THREE.LinearFilter
|
||||
@@ -321,9 +323,19 @@ watch(mode,(val)=>{
|
||||
})
|
||||
|
||||
onMounted(()=>{
|
||||
nextTick(()=>{
|
||||
setTimeout(init,100)
|
||||
// Use ResizeObserver to init only when container has dimensions
|
||||
const el=containerRef.value
|
||||
if(!el)return
|
||||
const ro=new ResizeObserver(entries=>{
|
||||
for(const e of entries){
|
||||
if(e.contentRect.width>0&&e.contentRect.height>0&&!renderer){
|
||||
init()
|
||||
ro.disconnect()
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
ro.observe(el)
|
||||
window.addEventListener('resize',onResize)
|
||||
})
|
||||
|
||||
@@ -336,9 +348,9 @@ onUnmounted(()=>{
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.viewer-wrap{display:flex;flex-direction:column;height:100%;background:#0a0a1a;color:#fff}
|
||||
.viewer-wrap{display:flex;flex-direction:column;min-height:600px;height:100%;background:#0a0a1a;color:#fff}
|
||||
.vbar{display:flex;gap:8px;padding:8px 12px;background:#1a1a2e;border-bottom:1px solid #333;align-items:center;flex-wrap:wrap}
|
||||
.vmain{flex:1;position:relative;overflow:hidden;background:#0a0a1a}
|
||||
.vmain{flex:1;position:relative;overflow:hidden;background:#0a0a1a;min-height:500px}
|
||||
.gl-canvas{width:100%;height:100%;display:block}
|
||||
.ov-tl{position:absolute;top:8px;left:8px;padding:6px 10px;background:rgba(0,0,0,.7);border-radius:4px;font-size:11px;font-family:'Courier New',monospace;color:#0f0;line-height:1.5;pointer-events:none;z-index:10}
|
||||
.ov-bl{position:absolute;bottom:8px;left:8px;padding:6px 10px;background:rgba(0,0,0,.7);border-radius:4px;font-size:11px;font-family:'Courier New',monospace;color:#0f0;pointer-events:none;z-index:10}
|
||||
|
||||
8
node_modules/.vite/deps/_metadata.json
generated
vendored
8
node_modules/.vite/deps/_metadata.json
generated
vendored
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"hash": "5905b5e1",
|
||||
"configHash": "4d078017",
|
||||
"lockfileHash": "9e11ee45",
|
||||
"browserHash": "09dcaa6f",
|
||||
"optimized": {},
|
||||
"chunks": {}
|
||||
}
|
||||
3
node_modules/.vite/deps/package.json
generated
vendored
3
node_modules/.vite/deps/package.json
generated
vendored
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
381
package-lock.json
generated
381
package-lock.json
generated
@@ -1,381 +0,0 @@
|
||||
{
|
||||
"name": "his",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"axios": "^1.13.2",
|
||||
"json-bigint": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"husky": "^9.1.7"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.17.0.tgz",
|
||||
"integrity": "sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.16.0",
|
||||
"form-data": "^4.0.5",
|
||||
"https-proxy-agent": "^5.0.1",
|
||||
"proxy-from-env": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/bignumber.js": {
|
||||
"version": "9.3.1",
|
||||
"resolved": "https://registry.npmmirror.com/bignumber.js/-/bignumber.js-9.3.1.tgz",
|
||||
"integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
|
||||
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
|
||||
"integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.16.0.tgz",
|
||||
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz",
|
||||
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/hasown": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.4.tgz",
|
||||
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "9.1.7",
|
||||
"resolved": "https://registry.npmmirror.com/husky/-/husky-9.1.7.tgz",
|
||||
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"husky": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/json-bigint": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz",
|
||||
"integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bignumber.js": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mime-db": "1.52.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,351 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Bug #318 历史数据修复脚本
|
||||
为已存在但未生成手术医嘱的手术申请单补齐数据
|
||||
"""
|
||||
|
||||
import psycopg2
|
||||
import json
|
||||
import random
|
||||
import string
|
||||
from datetime import datetime
|
||||
|
||||
# 数据库连接配置
|
||||
DB_CONFIG = {
|
||||
"host": "47.116.196.11",
|
||||
"port": 15432,
|
||||
"database": "postgresql",
|
||||
"user": "postgresql",
|
||||
"password": "postgresql", # 请根据实际情况修改
|
||||
}
|
||||
|
||||
|
||||
def generate_bus_no():
|
||||
"""生成4位随机bus_no"""
|
||||
return "".join(random.choices(string.digits, k=4))
|
||||
|
||||
|
||||
def check_repair_needed(conn):
|
||||
"""检查需要修复的记录数"""
|
||||
cursor = conn.cursor()
|
||||
sql = """
|
||||
SELECT COUNT(*)
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL
|
||||
"""
|
||||
cursor.execute(sql)
|
||||
count = cursor.fetchone()[0]
|
||||
cursor.close()
|
||||
return count
|
||||
|
||||
|
||||
def get_repair_list(conn):
|
||||
"""获取需要修复的手术申请单列表"""
|
||||
cursor = conn.cursor()
|
||||
sql = """
|
||||
SELECT
|
||||
rf.id,
|
||||
rf.prescription_no,
|
||||
rf.encounter_id,
|
||||
rf.patient_id,
|
||||
rf.requester_id,
|
||||
rf.create_time,
|
||||
rf.org_id,
|
||||
rf.desc_json
|
||||
FROM doc_request_form rf
|
||||
LEFT JOIN wor_service_request sr ON sr.prescription_no = rf.prescription_no
|
||||
AND sr.delete_flag = '0'
|
||||
WHERE rf.type_code = 'PROCEDURE'
|
||||
AND rf.delete_flag = '0'
|
||||
AND sr.id IS NULL
|
||||
ORDER BY rf.create_time DESC
|
||||
"""
|
||||
cursor.execute(sql)
|
||||
results = cursor.fetchall()
|
||||
cursor.close()
|
||||
return results
|
||||
|
||||
|
||||
def parse_surgery_info(desc_json):
|
||||
"""解析手术信息"""
|
||||
if not desc_json:
|
||||
return {}
|
||||
try:
|
||||
if isinstance(desc_json, str):
|
||||
return json.loads(desc_json)
|
||||
return desc_json
|
||||
except:
|
||||
return {}
|
||||
|
||||
|
||||
def repair_service_request(conn, repair_list):
|
||||
"""修复手术医嘱(ServiceRequest)"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
insert_sql = """
|
||||
INSERT INTO wor_service_request (
|
||||
bus_no, prescription_no, status_enum, generate_source_enum,
|
||||
therapy_enum, quantity, unit_code, category_enum,
|
||||
patient_id, requester_id, encounter_id, authored_time,
|
||||
org_id, content_json, delete_flag, create_time, create_by, tenant_id
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
RETURNING id
|
||||
"""
|
||||
|
||||
new_requests = []
|
||||
for record in repair_list:
|
||||
(
|
||||
rf_id,
|
||||
prescription_no,
|
||||
encounter_id,
|
||||
patient_id,
|
||||
requester_id,
|
||||
create_time,
|
||||
org_id,
|
||||
desc_json,
|
||||
) = record
|
||||
|
||||
# 解析手术信息
|
||||
surgery_info = parse_surgery_info(desc_json)
|
||||
content_json = (
|
||||
json.dumps(surgery_info, ensure_ascii=False) if surgery_info else None
|
||||
)
|
||||
|
||||
# 生成bus_no
|
||||
bus_no = generate_bus_no()
|
||||
|
||||
# 插入ServiceRequest
|
||||
cursor.execute(
|
||||
insert_sql,
|
||||
(
|
||||
bus_no, # bus_no
|
||||
prescription_no, # prescription_no
|
||||
1, # status_enum: 1-待签发
|
||||
1, # generate_source_enum: 1-医生处方
|
||||
2, # therapy_enum: 2-临时医嘱
|
||||
1, # quantity
|
||||
"次", # unit_code
|
||||
4, # category_enum: 4-手术
|
||||
patient_id, # patient_id
|
||||
requester_id, # requester_id
|
||||
encounter_id, # encounter_id
|
||||
create_time, # authored_time
|
||||
org_id, # org_id
|
||||
content_json, # content_json
|
||||
"0", # delete_flag
|
||||
create_time, # create_time
|
||||
requester_id, # create_by
|
||||
1, # tenant_id
|
||||
),
|
||||
)
|
||||
|
||||
service_request_id = cursor.fetchone()[0]
|
||||
new_requests.append(
|
||||
{
|
||||
"service_request_id": service_request_id,
|
||||
"bus_no": bus_no,
|
||||
"prescription_no": prescription_no,
|
||||
"patient_id": patient_id,
|
||||
"encounter_id": encounter_id,
|
||||
"requester_id": requester_id,
|
||||
"create_time": create_time,
|
||||
"org_id": org_id,
|
||||
"surgery_info": surgery_info,
|
||||
}
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
return new_requests
|
||||
|
||||
|
||||
def repair_charge_items(conn, new_requests):
|
||||
"""修复收费项目(ChargeItem)"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
insert_sql = """
|
||||
INSERT INTO adm_charge_item (
|
||||
bus_no, status_enum, generate_source_enum, patient_id,
|
||||
context_enum, encounter_id, enterer_id, entered_date,
|
||||
service_table, service_id, product_table, requesting_org_id,
|
||||
quantity_value, quantity_unit, unit_price, total_price,
|
||||
delete_flag, create_time, create_by, tenant_id
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
||||
"""
|
||||
|
||||
for req in new_requests:
|
||||
surgery_info = req["surgery_info"]
|
||||
|
||||
# 手术费用
|
||||
surgery_fee = 0
|
||||
if surgery_info and "surgeryFee" in surgery_info:
|
||||
try:
|
||||
surgery_fee = float(surgery_info["surgeryFee"])
|
||||
except:
|
||||
surgery_fee = 0
|
||||
|
||||
# 插入手术费用收费项目
|
||||
cursor.execute(
|
||||
insert_sql,
|
||||
(
|
||||
"CI" + req["bus_no"], # bus_no
|
||||
1, # status_enum: 1-草稿
|
||||
1, # generate_source_enum: 1-医生处方
|
||||
req["patient_id"], # patient_id
|
||||
3, # context_enum: 3-诊疗
|
||||
req["encounter_id"], # encounter_id
|
||||
req["requester_id"], # enterer_id
|
||||
req["create_time"], # entered_date
|
||||
"wor_service_request", # service_table
|
||||
req["service_request_id"], # service_id
|
||||
"wor_activity_definition", # product_table
|
||||
req["org_id"], # requesting_org_id
|
||||
1, # quantity_value
|
||||
"次", # quantity_unit
|
||||
surgery_fee, # unit_price
|
||||
surgery_fee, # total_price
|
||||
"0", # delete_flag
|
||||
req["create_time"], # create_time
|
||||
req["requester_id"], # create_by
|
||||
1, # tenant_id
|
||||
),
|
||||
)
|
||||
|
||||
# 麻醉费用(如果存在且大于0)
|
||||
anesthesia_fee = 0
|
||||
if surgery_info and "anesthesiaFee" in surgery_info:
|
||||
try:
|
||||
anesthesia_fee = float(surgery_info["anesthesiaFee"])
|
||||
except:
|
||||
anesthesia_fee = 0
|
||||
|
||||
if anesthesia_fee > 0:
|
||||
cursor.execute(
|
||||
insert_sql,
|
||||
(
|
||||
"CI" + req["bus_no"] + "_A", # bus_no
|
||||
1, # status_enum
|
||||
1, # generate_source_enum
|
||||
req["patient_id"], # patient_id
|
||||
3, # context_enum
|
||||
req["encounter_id"], # encounter_id
|
||||
req["requester_id"], # enterer_id
|
||||
req["create_time"], # entered_date
|
||||
"wor_service_request", # service_table
|
||||
req["service_request_id"], # service_id
|
||||
"wor_activity_definition", # product_table
|
||||
req["org_id"], # requesting_org_id
|
||||
1, # quantity_value
|
||||
"次", # quantity_unit
|
||||
anesthesia_fee, # unit_price
|
||||
anesthesia_fee, # total_price
|
||||
"0", # delete_flag
|
||||
req["create_time"], # create_time
|
||||
req["requester_id"], # create_by
|
||||
1, # tenant_id
|
||||
),
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
cursor.close()
|
||||
|
||||
|
||||
def verify_repair(conn):
|
||||
"""验证修复结果"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 统计手术医嘱数量
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*)
|
||||
FROM wor_service_request
|
||||
WHERE category_enum = 4 AND delete_flag = '0'
|
||||
""")
|
||||
service_request_count = cursor.fetchone()[0]
|
||||
|
||||
# 统计收费项目数量
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*)
|
||||
FROM adm_charge_item ci
|
||||
WHERE ci.service_table = 'wor_service_request'
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM wor_service_request sr
|
||||
WHERE sr.id = ci.service_id AND sr.category_enum = 4
|
||||
)
|
||||
""")
|
||||
charge_item_count = cursor.fetchone()[0]
|
||||
|
||||
cursor.close()
|
||||
return service_request_count, charge_item_count
|
||||
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
print("=" * 60)
|
||||
print("Bug #318 历史数据修复脚本")
|
||||
print("=" * 60)
|
||||
print()
|
||||
|
||||
try:
|
||||
# 连接数据库
|
||||
print("正在连接数据库...")
|
||||
conn = psycopg2.connect(**DB_CONFIG)
|
||||
print("✓ 数据库连接成功")
|
||||
print()
|
||||
|
||||
# 步骤1:检查需要修复的记录数
|
||||
print("步骤1: 检查需要修复的记录...")
|
||||
need_repair_count = check_repair_needed(conn)
|
||||
print(f"✓ 发现 {need_repair_count} 条需要修复的手术申请单")
|
||||
print()
|
||||
|
||||
if need_repair_count == 0:
|
||||
print("没有需要修复的数据,退出")
|
||||
return
|
||||
|
||||
# 步骤2:获取修复列表
|
||||
print("步骤2: 获取修复列表...")
|
||||
repair_list = get_repair_list(conn)
|
||||
print(f"✓ 获取到 {len(repair_list)} 条记录")
|
||||
print()
|
||||
|
||||
# 步骤3:修复ServiceRequest
|
||||
print("步骤3: 生成手术医嘱(ServiceRequest)...")
|
||||
new_requests = repair_service_request(conn, repair_list)
|
||||
print(f"✓ 成功生成 {len(new_requests)} 条手术医嘱")
|
||||
print()
|
||||
|
||||
# 步骤4:修复ChargeItem
|
||||
print("步骤4: 生成收费项目(ChargeItem)...")
|
||||
repair_charge_items(conn, new_requests)
|
||||
print(f"✓ 成功生成收费项目")
|
||||
print()
|
||||
|
||||
# 步骤5:验证修复结果
|
||||
print("步骤5: 验证修复结果...")
|
||||
service_count, charge_count = verify_repair(conn)
|
||||
print(f"✓ 当前手术医嘱总数: {service_count}")
|
||||
print(f"✓ 当前手术收费项目总数: {charge_count}")
|
||||
print()
|
||||
|
||||
print("=" * 60)
|
||||
print("✓ 修复完成!")
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"✗ 错误: {e}")
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
if "conn" in locals():
|
||||
conn.close()
|
||||
print("\n数据库连接已关闭")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,156 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# sync-ai-rules.sh — 将 RULES.md 完整内容同步到所有 AI 工具配置文件
|
||||
#
|
||||
# 用法: bash scripts/sync-ai-rules.sh
|
||||
#
|
||||
# 设计原则:
|
||||
# RULES.md 是唯一信源,本脚本将其内容嵌入到各工具配置文件
|
||||
# 开发者只需编辑 RULES.md,然后运行本脚本即可同步所有工具
|
||||
# ============================================================
|
||||
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
RULES_FILE="RULES.md"
|
||||
if [ ! -f "$RULES_FILE" ]; then
|
||||
echo "❌ $RULES_FILE not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RULES_CONTENT=$(cat "$RULES_FILE")
|
||||
TIMESTAMP=$(date '+%Y-%m-%d %H:%M')
|
||||
|
||||
echo "📝 Syncing RULES.md → AI tool configs..."
|
||||
|
||||
# ============================================================
|
||||
# 1. AGENTS.md (Codex CLI / Claude Code)
|
||||
# ============================================================
|
||||
cat > AGENTS.md << HEREDOC
|
||||
# HealthLink-HIS — AI 开发规范
|
||||
|
||||
> 🤖 本文件由 Codex CLI、Claude Code 等工具自动读取。
|
||||
> 工具进入项目目录时会自动加载此文件作为开发规范上下文。
|
||||
|
||||
---
|
||||
|
||||
${RULES_CONTENT}
|
||||
|
||||
---
|
||||
|
||||
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
|
||||
HEREDOC
|
||||
echo " ✅ AGENTS.md"
|
||||
|
||||
# ============================================================
|
||||
# 2. .cursorrules (Cursor IDE / Codeium Windsurf)
|
||||
# ============================================================
|
||||
cat > .cursorrules << HEREDOC
|
||||
# HealthLink-HIS — AI 开发规范 (Cursor)
|
||||
|
||||
> 🤖 Cursor IDE 打开本项目时自动加载此文件。
|
||||
|
||||
---
|
||||
|
||||
${RULES_CONTENT}
|
||||
|
||||
---
|
||||
|
||||
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
|
||||
HEREDOC
|
||||
echo " ✅ .cursorrules"
|
||||
|
||||
# ============================================================
|
||||
# 3. .github/copilot-instructions.md (GitHub Copilot)
|
||||
# ============================================================
|
||||
mkdir -p .github
|
||||
cat > .github/copilot-instructions.md << HEREDOC
|
||||
# HealthLink-HIS — AI 开发规范 (GitHub Copilot)
|
||||
|
||||
> 🤖 GitHub Copilot 打开本项目时自动加载此文件。
|
||||
|
||||
---
|
||||
|
||||
${RULES_CONTENT}
|
||||
|
||||
---
|
||||
|
||||
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
|
||||
HEREDOC
|
||||
echo " ✅ .github/copilot-instructions.md"
|
||||
|
||||
# ============================================================
|
||||
# 4. .windsurfrules (Windsurf / Codeium)
|
||||
# ============================================================
|
||||
cat > .windsurfrules << HEREDOC
|
||||
# HealthLink-HIS — AI 开发规范 (Windsurf)
|
||||
|
||||
> 🤖 Windsurf 打开本项目时自动加载此文件。
|
||||
|
||||
---
|
||||
|
||||
${RULES_CONTENT}
|
||||
|
||||
---
|
||||
|
||||
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
|
||||
HEREDOC
|
||||
echo " ✅ .windsurfrules"
|
||||
|
||||
# ============================================================
|
||||
# 5. .clinerules (Cline)
|
||||
# ============================================================
|
||||
cat > .clinerules << HEREDOC
|
||||
# HealthLink-HIS — AI 开发规范 (Cline)
|
||||
|
||||
> 🤖 Cline 打开本项目时自动加载此文件。
|
||||
|
||||
---
|
||||
|
||||
${RULES_CONTENT}
|
||||
|
||||
---
|
||||
|
||||
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
|
||||
HEREDOC
|
||||
echo " ✅ .clinerules"
|
||||
|
||||
# ============================================================
|
||||
# 6. .qwenrules (Qwen Coder / 通义灵码)
|
||||
# ============================================================
|
||||
cat > .qwenrules << HEREDOC
|
||||
# HealthLink-HIS — AI 开发规范 (Qwen Coder)
|
||||
|
||||
> 🤖 通义灵码 / Qwen Coder 打开本项目时自动加载此文件。
|
||||
|
||||
---
|
||||
|
||||
${RULES_CONTENT}
|
||||
|
||||
---
|
||||
|
||||
> 📅 最后同步: ${TIMESTAMP} | 源文件: RULES.md | 重新同步: \`bash scripts/sync-ai-rules.sh\`
|
||||
HEREDOC
|
||||
echo " ✅ .qwenrules"
|
||||
|
||||
# ============================================================
|
||||
# 7. .aider.conf.yml (Aider) — YAML格式,嵌入指令
|
||||
# ============================================================
|
||||
# Aider 支持 instruction-files 指向文件,同时也支持直接在 .aider.conf.yml 中写 instructions
|
||||
# 这里用 instructions 指令把内容内联
|
||||
cat > .aider.conf.yml << HEREDOC
|
||||
# Aider configuration for HealthLink-HIS
|
||||
# Aider 自动读取此文件获取开发规范
|
||||
|
||||
instructions: |
|
||||
$(echo "$RULES_CONTENT" | sed 's/^/ /')
|
||||
HEREDOC
|
||||
echo " ✅ .aider.conf.yml"
|
||||
|
||||
echo ""
|
||||
echo "🎉 All 7 AI tool configs synced from RULES.md"
|
||||
echo " 文件大小:"
|
||||
for f in AGENTS.md .cursorrules .github/copilot-instructions.md .windsurfrules .clinerules .qwenrules .aider.conf.yml; do
|
||||
size=$(wc -c < "$f" 2>/dev/null || echo "0")
|
||||
echo " $f: ${size} bytes"
|
||||
done
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user