From b0850257c8ab9a2359e0ba69bc5506a14db3f066 Mon Sep 17 00:00:00 2001 From: chenqi Date: Tue, 6 Jan 2026 16:23:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(surgery):=20=E5=AE=8C=E5=96=84=E6=89=8B?= =?UTF-8?q?=E6=9C=AF=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加手术申请相关API接口,包括根据患者ID查询就诊列表功能 - 在医生工作站界面集成手术申请功能选项卡 - 实现手术管理页面的完整功能,包括手术申请的增删改查 - 添加手术排期、开始、完成等状态流转功能 - 优化手术管理页面表格展示,增加手术类型、等级、计划时间等字段 - 实现手术申请表单的完整编辑和查看模式 - 集成患者信息和就诊记录关联功能 - 添加手术室、医生、护士等资源选择功能 - 更新系统依赖配置,添加core-common模块 - 优化图标资源和manifest配置文件 - 调整患者档案和门诊记录相关状态枚举 --- .trae/rules/project_rules.md | 0 check_surgery_fields.sql | 10 + fill_missing_surgery_name_fields.sql | 82 ++ openhis-server-new/core-framework/pom.xml | 5 + .../appservice/IOperatingRoomAppService.java | 77 ++ .../impl/OperatingRoomAppServiceImpl.java | 293 ++++++ .../controller/OperatingRoomController.java | 112 +++ .../basedatamanage/dto/OperatingRoomDto.java | 93 ++ .../OutpatientRegistrationAppServiceImpl.java | 23 +- .../appservice/ISurgeryAppService.java | 11 + .../impl/SurgeryAppServiceImpl.java | 356 +++++++- .../controller/SurgeryController.java | 14 + .../web/clinicalmanage/dto/SurgeryDto.java | 26 +- .../web/common/appservice/ICommonService.java | 8 + .../appservice/impl/CommonServiceImpl.java | 20 + .../appservice/ITodayOutpatientService.java | 105 +++ .../impl/TodayOutpatientServiceImpl.java | 305 +++++++ .../controller/TodayOutpatientController.java | 181 ++++ .../dto/TodayOutpatientPatientDto.java | 132 +++ .../dto/TodayOutpatientQueryParam.java | 92 ++ .../dto/TodayOutpatientStatsDto.java | 52 ++ .../mapper/TodayOutpatientMapper.java | 204 +++++ ...entMedicalRecordHomePageCollectionDto.java | 8 +- .../src/main/resources/application-dev.yml | 6 +- .../mapper/clinicalmanage/SurgeryMapper.xml | 71 +- .../openhis/common/enums/AssignSeqEnum.java | 7 +- .../openhis/common/utils/HisQueryUtils.java | 34 +- .../administration/domain/OperatingRoom.java | 61 ++ .../mapper/OperatingRoomMapper.java | 15 + .../service/IOperatingRoomService.java | 13 + .../impl/OperatingRoomServiceImpl.java | 18 + .../com/openhis/clinical/domain/Surgery.java | 64 +- .../service/impl/SurgeryServiceImpl.java | 53 +- openhis-server-new/pom.xml | 6 - openhis-ui-vue3/favicon/site.webmanifest | 13 +- openhis-ui-vue3/index.html | 4 +- openhis-ui-vue3/src/api/operatingroom.js | 90 ++ openhis-ui-vue3/src/api/surgerymanage.js | 13 + .../src/assets/icons/svg/patient.svg | 2 +- .../src/assets/icons/svg/redis-list.svg | 2 +- openhis-ui-vue3/src/router/index.js | 88 +- .../components/surgery/surgeryApplication.vue | 715 +++++++++++++++ .../TodayOutpatientPatientList.vue | 633 +++++++++++++ .../todayOutpatient/TodayOutpatientStats.vue | 303 +++++++ .../components/todayOutpatient/api.js | 95 ++ .../components/todayOutpatient/index.vue | 753 ++++++++++++++++ .../src/views/doctorstation/index.vue | 9 + .../views/doctorstation/todayOutpatient.vue | 372 ++++++++ openhis-ui-vue3/src/views/index.vue | 5 +- .../src/views/operatingroom/index.vue | 501 +++++++++++ .../outpatienrecords/index.vue | 21 +- .../src/views/surgerymanage/index.vue | 840 +++++++++++++++--- sql/手术室管理表结构.sql | 13 + verify_surgery_name_fields.sql | 56 ++ 填充手术人员字段姓名.sql | 18 + 手术人员字段不显示问题解决方案.md | 254 ++++++ 手术申请医生科室字段保存问题解决方案.md | 215 +++++ 手术申请医生科室数据保存问题排查指南.md | 194 ++++ 检查和填充手术人员字段.sql | 113 +++ 测试手术表插入.sql | 58 ++ .../20250104_update_cli_surgery_tenant_id.sql | 12 + .../20250105_add_apply_doctor_dept_name_simple.sql | 1 + ...0105_add_apply_doctor_dept_name_to_cli_surgery.sql | 30 + .../add_apply_doctor_fields_to_cli_surgery.sql | 0 .../fix_cli_surgery_missing_columns.sql | 12 + 验证手术申请医生科室数据.sql | 4 + 66 files changed, 7683 insertions(+), 313 deletions(-) create mode 100644 .trae/rules/project_rules.md create mode 100644 check_surgery_fields.sql create mode 100644 fill_missing_surgery_name_fields.sql create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/IOperatingRoomAppService.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OperatingRoomAppServiceImpl.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/controller/OperatingRoomController.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/dto/OperatingRoomDto.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/ITodayOutpatientService.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/TodayOutpatientServiceImpl.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/TodayOutpatientController.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientPatientDto.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientQueryParam.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientStatsDto.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/mapper/TodayOutpatientMapper.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/domain/OperatingRoom.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/mapper/OperatingRoomMapper.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOperatingRoomService.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OperatingRoomServiceImpl.java create mode 100644 openhis-ui-vue3/src/api/operatingroom.js create mode 100644 openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue create mode 100644 openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue create mode 100644 openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientStats.vue create mode 100644 openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/api.js create mode 100644 openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/index.vue create mode 100644 openhis-ui-vue3/src/views/doctorstation/todayOutpatient.vue create mode 100644 openhis-ui-vue3/src/views/operatingroom/index.vue create mode 100644 sql/手术室管理表结构.sql create mode 100644 verify_surgery_name_fields.sql create mode 100644 填充手术人员字段姓名.sql create mode 100644 手术人员字段不显示问题解决方案.md create mode 100644 手术申请医生科室字段保存问题解决方案.md create mode 100644 手术申请医生科室数据保存问题排查指南.md create mode 100644 检查和填充手术人员字段.sql create mode 100644 测试手术表插入.sql create mode 100644 迁移记录-DB变更记录/20250104_update_cli_surgery_tenant_id.sql create mode 100644 迁移记录-DB变更记录/20250105_add_apply_doctor_dept_name_simple.sql create mode 100644 迁移记录-DB变更记录/20250105_add_apply_doctor_dept_name_to_cli_surgery.sql create mode 100644 迁移记录-DB变更记录/add_apply_doctor_fields_to_cli_surgery.sql create mode 100644 迁移记录-DB变更记录/fix_cli_surgery_missing_columns.sql create mode 100644 验证手术申请医生科室数据.sql diff --git a/.trae/rules/project_rules.md b/.trae/rules/project_rules.md new file mode 100644 index 00000000..e69de29b diff --git a/check_surgery_fields.sql b/check_surgery_fields.sql new file mode 100644 index 00000000..ccd07989 --- /dev/null +++ b/check_surgery_fields.sql @@ -0,0 +1,10 @@ +-- 检查手术表中所有字段是否存在 +SELECT + column_name, + data_type, + character_maximum_length, + is_nullable +FROM information_schema.columns +WHERE table_name = 'cli_surgery' +AND column_name LIKE '%name%' +ORDER BY column_name; \ No newline at end of file diff --git a/fill_missing_surgery_name_fields.sql b/fill_missing_surgery_name_fields.sql new file mode 100644 index 00000000..17f87892 --- /dev/null +++ b/fill_missing_surgery_name_fields.sql @@ -0,0 +1,82 @@ +-- 修复已存在的手术记录中缺失的名称字段 +-- 注意:这只是一个示例,实际执行前请根据您的数据库表结构调整 + +-- 填充患者姓名 +UPDATE public.cli_surgery s +SET patient_name = p.name +FROM public.adm_patient p +WHERE s.patient_id = p.id +AND s.patient_name IS NULL +AND s.delete_flag = '0'; + +-- 填充主刀医生姓名 +UPDATE public.cli_surgery s +SET main_surgeon_name = u.nick_name +FROM public.sys_user u +WHERE s.main_surgeon_id = u.user_id +AND s.main_surgeon_name IS NULL +AND s.delete_flag = '0'; + +-- 填充麻醉医生姓名 +UPDATE public.cli_surgery s +SET anesthetist_name = u.nick_name +FROM public.sys_user u +WHERE s.anesthetist_id = u.user_id +AND s.anesthetist_name IS NULL +AND s.delete_flag = '0'; + +-- 填充助手1姓名 +UPDATE public.cli_surgery s +SET assistant_1_name = u.nick_name +FROM public.sys_user u +WHERE s.assistant_1_id = u.user_id +AND s.assistant_1_name IS NULL +AND s.delete_flag = '0'; + +-- 填充助手2姓名 +UPDATE public.cli_surgery s +SET assistant_2_name = u.nick_name +FROM public.sys_user u +WHERE s.assistant_2_id = u.user_id +AND s.assistant_2_name IS NULL +AND s.delete_flag = '0'; + +-- 填充巡回护士姓名 +UPDATE public.cli_surgery s +SET scrub_nurse_name = u.nick_name +FROM public.sys_user u +WHERE s.scrub_nurse_id = u.user_id +AND s.scrub_nurse_name IS NULL +AND s.delete_flag = '0'; + +-- 填充手术室名称 +UPDATE public.cli_surgery s +SET operating_room_name = r.name +FROM public.cli_operating_room r +WHERE s.operating_room_id = r.id +AND s.operating_room_name IS NULL +AND s.delete_flag = '0'; + +-- 填充执行科室名称 +UPDATE public.cli_surgery s +SET org_name = o.name +FROM public.adm_organization o +WHERE s.org_id = o.id +AND s.org_name IS NULL +AND s.delete_flag = '0'; + +-- 填充申请科室名称 +UPDATE public.cli_surgery s +SET apply_dept_name = o.name +FROM public.adm_organization o +WHERE s.apply_dept_id = o.id +AND s.apply_dept_name IS NULL +AND s.delete_flag = '0'; + +-- 填充申请医生姓名 +UPDATE public.cli_surgery s +SET apply_doctor_name = u.nick_name +FROM public.sys_user u +WHERE s.apply_doctor_id = u.user_id +AND s.apply_doctor_name IS NULL +AND s.delete_flag = '0'; \ No newline at end of file diff --git a/openhis-server-new/core-framework/pom.xml b/openhis-server-new/core-framework/pom.xml index 4b4c44ac..08dc1f46 100644 --- a/openhis-server-new/core-framework/pom.xml +++ b/openhis-server-new/core-framework/pom.xml @@ -60,6 +60,11 @@ core-system + + com.core + core-common + + com.github.jsqlparser diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/IOperatingRoomAppService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/IOperatingRoomAppService.java new file mode 100644 index 00000000..067cb559 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/IOperatingRoomAppService.java @@ -0,0 +1,77 @@ +package com.openhis.web.basedatamanage.appservice; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.core.common.core.domain.R; +import com.openhis.web.basedatamanage.dto.OperatingRoomDto; +import org.springframework.validation.annotation.Validated; + +import javax.servlet.http.HttpServletRequest; + +/** + * 手术室应用Service接口 + * + * @author system + * @date 2026-01-04 + */ +public interface IOperatingRoomAppService { + + /** + * 分页查询手术室列表 + * + * @param operatingRoomDto 查询条件 + * @param pageNo 当前页 + * @param pageSize 每页条数 + * @param request 请求 + * @return 手术室列表 + */ + R getOperatingRoomPage(OperatingRoomDto operatingRoomDto, Integer pageNo, Integer pageSize, + HttpServletRequest request); + + /** + * 根据ID查询手术室详情 + * + * @param id 手术室ID + * @return 手术室详情 + */ + R getOperatingRoomById(Long id); + + /** + * 新增手术室 + * + * @param operatingRoomDto 手术室信息 + * @return 结果 + */ + R addOperatingRoom(@Validated OperatingRoomDto operatingRoomDto); + + /** + * 修改手术室 + * + * @param operatingRoomDto 手术室信息 + * @return 结果 + */ + R updateOperatingRoom(@Validated OperatingRoomDto operatingRoomDto); + + /** + * 删除手术室 + * + * @param ids 手术室ID(支持批量) + * @return 结果 + */ + R deleteOperatingRoom(String ids); + + /** + * 启用手术室 + * + * @param ids 手术室ID数组 + * @return 结果 + */ + R enableOperatingRoom(java.util.List ids); + + /** + * 停用手术室 + * + * @param ids 手术室ID数组 + * @return 结果 + */ + R disableOperatingRoom(java.util.List ids); +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OperatingRoomAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OperatingRoomAppServiceImpl.java new file mode 100644 index 00000000..98fabb54 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OperatingRoomAppServiceImpl.java @@ -0,0 +1,293 @@ +package com.openhis.web.basedatamanage.appservice.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.core.common.core.domain.R; +import com.core.common.utils.AssignSeqUtil; +import com.core.common.utils.ChineseConvertUtils; +import com.core.common.utils.StringUtils; +import com.openhis.administration.domain.OperatingRoom; +import com.openhis.administration.mapper.OperatingRoomMapper; +import com.openhis.administration.service.IOperatingRoomService; +import org.springframework.beans.BeanUtils; +import com.openhis.common.enums.AssignSeqEnum; +import com.openhis.common.enums.LocationStatus; +import com.openhis.common.utils.HisPageUtils; +import com.openhis.common.utils.HisQueryUtils; +import com.openhis.web.basedatamanage.appservice.IOperatingRoomAppService; +import com.openhis.web.basedatamanage.dto.OperatingRoomDto; +import com.openhis.web.common.appservice.ICommonService; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +/** + * 手术室应用Service实现类 + * + * @author system + * @date 2026-01-04 + */ +@Service +public class OperatingRoomAppServiceImpl implements IOperatingRoomAppService { + + @Resource + private IOperatingRoomService operatingRoomService; + + @Resource + private OperatingRoomMapper operatingRoomMapper; + + @Resource + private AssignSeqUtil assignSeqUtil; + + @Resource + private ICommonService commonService; + + /** + * 分页查询手术室列表 + * + * @param operatingRoomDto 查询条件 + * @param pageNo 当前页 + * @param pageSize 每页条数 + * @param request 请求 + * @return 手术室列表 + */ + @Override + public R getOperatingRoomPage(OperatingRoomDto operatingRoomDto, Integer pageNo, Integer pageSize, + HttpServletRequest request) { + // 构建查询条件 + QueryWrapper queryWrapper = HisQueryUtils.buildQueryWrapper(operatingRoomDto, + operatingRoomDto.getName(), + new HashSet<>(Arrays.asList("name", "py_str", "wb_str")), request); + + // 设置排序 + queryWrapper.orderByDesc("display_order").orderByDesc("create_time"); + + // 查询手术室分页列表 + Page operatingRoomPage = + HisPageUtils.selectPage(operatingRoomMapper, queryWrapper, pageNo, pageSize, OperatingRoomDto.class); + + // 处理枚举字段显示文本 + operatingRoomPage.getRecords().forEach(e -> { + // 状态 + e.setStatusEnum_dictText(e.getStatusEnum() != null && e.getStatusEnum() == 1 ? "启用" : "停用"); + // 拼音码 + e.setPyStr(ChineseConvertUtils.toPinyinFirstLetter(e.getName())); + // 五笔码 + e.setWbStr(ChineseConvertUtils.toWBFirstLetter(e.getName())); + }); + + return R.ok(operatingRoomPage); + } + + /** + * 根据ID查询手术室详情 + * + * @param id 手术室ID + * @return 手术室详情 + */ + @Override + public R getOperatingRoomById(Long id) { + OperatingRoom operatingRoom = operatingRoomService.getById(id); + if (operatingRoom == null) { + return R.fail("手术室信息不存在"); + } + + OperatingRoomDto operatingRoomDto = new OperatingRoomDto(); + BeanUtils.copyProperties(operatingRoom, operatingRoomDto); + + // 状态描述 + operatingRoomDto.setStatusEnum_dictText( + operatingRoom.getStatusEnum() != null && operatingRoom.getStatusEnum() == 1 ? "启用" : "停用"); + + // 如果有机构ID,查询机构名称 + if (operatingRoom.getOrganizationId() != null) { + String orgName = commonService.getOrgNameById(operatingRoom.getOrganizationId()); + operatingRoomDto.setOrganizationName(orgName); + } + + return R.ok(operatingRoomDto); + } + + /** + * 新增手术室 + * + * @param operatingRoomDto 手术室信息 + * @return 结果 + */ + @Override + public R addOperatingRoom(OperatingRoomDto operatingRoomDto) { + // 校验名称不能为空 + if (StringUtils.isEmpty(operatingRoomDto.getName())) { + return R.fail("手术室名称不能为空"); + } + + // 去除空格 + String name = operatingRoomDto.getName().replaceAll("[  ]", ""); + operatingRoomDto.setName(name); + + // 判断是否存在同名 + if (isExistName(name, null)) { + return R.fail("【" + name + "】已存在"); + } + + OperatingRoom operatingRoom = new OperatingRoom(); + BeanUtils.copyProperties(operatingRoomDto, operatingRoom); + + // 生成编码 + String code = assignSeqUtil.getSeq(AssignSeqEnum.OPERATING_ROOM_BUS_NO.getPrefix(), 3); + operatingRoom.setBusNo(code); + + // 拼音码 + operatingRoom.setPyStr(ChineseConvertUtils.toPinyinFirstLetter(operatingRoomDto.getName())); + // 五笔码 + operatingRoom.setWbStr(ChineseConvertUtils.toWBFirstLetter(operatingRoomDto.getName())); + + boolean result = operatingRoomService.save(operatingRoom); + if (result) { + return R.ok(null, "新增成功"); + } + return R.fail("新增失败"); + } + + /** + * 修改手术室 + * + * @param operatingRoomDto 手术室信息 + * @return 结果 + */ + @Override + public R updateOperatingRoom(OperatingRoomDto operatingRoomDto) { + // 校验手术室是否存在 + OperatingRoom existOperatingRoom = operatingRoomService.getById(operatingRoomDto.getId()); + if (existOperatingRoom == null) { + return R.fail("手术室信息不存在"); + } + + // 校验名称不能为空 + if (StringUtils.isEmpty(operatingRoomDto.getName())) { + return R.fail("手术室名称不能为空"); + } + + // 去除空格 + String name = operatingRoomDto.getName().replaceAll("[  ]", ""); + operatingRoomDto.setName(name); + + // 判断是否存在同名(排除自己) + if (isExistName(name, operatingRoomDto.getId())) { + return R.fail("【" + name + "】已存在"); + } + + OperatingRoom operatingRoom = new OperatingRoom(); + BeanUtils.copyProperties(operatingRoomDto, operatingRoom); + + // 拼音码 + operatingRoom.setPyStr(ChineseConvertUtils.toPinyinFirstLetter(operatingRoomDto.getName())); + // 五笔码 + operatingRoom.setWbStr(ChineseConvertUtils.toWBFirstLetter(operatingRoomDto.getName())); + + boolean result = operatingRoomService.updateById(operatingRoom); + if (result) { + return R.ok(null, "修改成功"); + } + return R.fail("修改失败"); + } + + /** + * 删除手术室 + * + * @param ids 手术室ID(支持批量) + * @return 结果 + */ + @Override + public R deleteOperatingRoom(String ids) { + // 解析ID字符串 + String[] idArray = ids.split(","); + List idList = new ArrayList<>(); + for (String idStr : idArray) { + try { + idList.add(Long.parseLong(idStr.trim())); + } catch (NumberFormatException e) { + return R.fail("ID格式错误"); + } + } + + // 删除手术室 + boolean result = operatingRoomService.removeByIds(idList); + if (result) { + return R.ok(null, "删除成功"); + } + return R.fail("删除失败"); + } + + /** + * 启用手术室 + * + * @param ids 手术室ID数组 + * @return 结果 + */ + @Override + public R enableOperatingRoom(List ids) { + if (ids == null || ids.isEmpty()) { + return R.fail("请选择要启用的手术室"); + } + + // 批量更新状态为启用 + List operatingRooms = operatingRoomService.listByIds(ids); + for (OperatingRoom operatingRoom : operatingRooms) { + operatingRoom.setStatusEnum(LocationStatus.ACTIVE.getValue()); + } + + boolean result = operatingRoomService.updateBatchById(operatingRooms); + if (result) { + return R.ok("启用成功"); + } + return R.fail("启用失败"); + } + + /** + * 停用手术室 + * + * @param ids 手术室ID数组 + * @return 结果 + */ + @Override + public R disableOperatingRoom(List ids) { + if (ids == null || ids.isEmpty()) { + return R.fail("请选择要停用的手术室"); + } + + // 批量更新状态为停用 + List operatingRooms = operatingRoomService.listByIds(ids); + for (OperatingRoom operatingRoom : operatingRooms) { + operatingRoom.setStatusEnum(LocationStatus.INACTIVE.getValue()); + } + + boolean result = operatingRoomService.updateBatchById(operatingRooms); + if (result) { + return R.ok("停用成功"); + } + return R.fail("停用失败"); + } + + /** + * 判断名称是否已存在 + * + * @param name 名称 + * @param excludeId 排除的ID + * @return 是否存在 + */ + private boolean isExistName(String name, Long excludeId) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(OperatingRoom::getName, name); + if (excludeId != null) { + queryWrapper.ne(OperatingRoom::getId, excludeId); + } + return operatingRoomService.count(queryWrapper) > 0; + } +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/controller/OperatingRoomController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/controller/OperatingRoomController.java new file mode 100644 index 00000000..164ae94d --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/controller/OperatingRoomController.java @@ -0,0 +1,112 @@ +package com.openhis.web.basedatamanage.controller; + +import com.core.common.core.domain.R; +import com.openhis.web.basedatamanage.appservice.IOperatingRoomAppService; +import com.openhis.web.basedatamanage.dto.OperatingRoomDto; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * 手术室管理Controller + * + * @author system + * @date 2026-01-04 + */ +@RestController +@RequestMapping("/base-data-manage/operating-room") +@Slf4j +@AllArgsConstructor +public class OperatingRoomController { + + @Resource + private IOperatingRoomAppService operatingRoomAppService; + + /** + * 分页查询手术室列表 + * + * @param operatingRoomDto 查询条件 + * @param pageNo 当前页码 + * @param pageSize 查询条数 + * @param request 请求 + * @return 手术室列表 + */ + @GetMapping(value = "/list") + public R getOperatingRoomPage(OperatingRoomDto operatingRoomDto, + @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, + @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize, + HttpServletRequest request) { + return operatingRoomAppService.getOperatingRoomPage(operatingRoomDto, pageNo, pageSize, request); + } + + /** + * 获取手术室详情 + * + * @param id 手术室ID + * @return 手术室详情 + */ + @GetMapping("/{id}") + public R getOperatingRoomById(@PathVariable Long id) { + return operatingRoomAppService.getOperatingRoomById(id); + } + + /** + * 新增手术室 + * + * @param operatingRoomDto 手术室信息 + * @return 操作结果 + */ + @PostMapping + public R addOperatingRoom(@Validated @RequestBody OperatingRoomDto operatingRoomDto) { + return operatingRoomAppService.addOperatingRoom(operatingRoomDto); + } + + /** + * 修改手术室 + * + * @param operatingRoomDto 手术室信息 + * @return 操作结果 + */ + @PutMapping + public R updateOperatingRoom(@Validated @RequestBody OperatingRoomDto operatingRoomDto) { + return operatingRoomAppService.updateOperatingRoom(operatingRoomDto); + } + + /** + * 删除手术室 + * + * @param ids 手术室ID(支持批量) + * @return 操作结果 + */ + @DeleteMapping("/{ids}") + public R deleteOperatingRoom(@PathVariable String ids) { + return operatingRoomAppService.deleteOperatingRoom(ids); + } + + /** + * 启用手术室 + * + * @param ids 手术室ID数组 + * @return 操作结果 + */ + @PutMapping("/enable") + public R enableOperatingRoom(@RequestBody List ids) { + return operatingRoomAppService.enableOperatingRoom(ids); + } + + /** + * 停用手术室 + * + * @param ids 手术室ID数组 + * @return 操作结果 + */ + @PutMapping("/disable") + public R disableOperatingRoom(@RequestBody List ids) { + return operatingRoomAppService.disableOperatingRoom(ids); + } +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/dto/OperatingRoomDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/dto/OperatingRoomDto.java new file mode 100644 index 00000000..5ca30778 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/dto/OperatingRoomDto.java @@ -0,0 +1,93 @@ +package com.openhis.web.basedatamanage.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 手术室DTO + * + * @author system + * @date 2026-01-04 + */ +@Data +@Accessors(chain = true) +public class OperatingRoomDto implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 编码 + */ + private String busNo; + + /** + * 手术室名称 + */ + private String name; + + /** + * 所属机构ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long organizationId; + + /** + * 机构名称 + */ + private String organizationName; + + /** + * 位置描述 + */ + private String locationDescription; + + /** + * 设备配置 + */ + private String equipmentConfig; + + /** + * 容纳人数 + */ + private Integer capacity; + + /** + * 状态编码 + */ + private Integer statusEnum; + + /** + * 状态描述 + */ + private String statusEnum_dictText; + + /** + * 显示顺序 + */ + private Integer displayOrder; + + /** + * 拼音码 + */ + private String pyStr; + + /** + * 五笔码 + */ + private String wbStr; + + /** + * 备注 + */ + private String remark; +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java index 2eba0576..17fa7047 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/chargemanage/appservice/impl/OutpatientRegistrationAppServiceImpl.java @@ -37,10 +37,7 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; /** @@ -119,6 +116,19 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra List patientIdList = iEncounterService.list().stream().map(e -> e.getPatientId()).collect(Collectors.toList()); + // 一次性获取所有患者标识 + List patientIds = patientMetadataPage.getRecords().stream() + .map(PatientMetadata::getId) + .collect(Collectors.toList()); + final Map> patientIdentifierMap; + if (!patientIds.isEmpty()) { + patientIdentifierMap = patientIdentifierService.list( + new LambdaQueryWrapper().in(PatientIdentifier::getPatientId, patientIds) + ).stream().collect(Collectors.groupingBy(PatientIdentifier::getPatientId)); + } else { + patientIdentifierMap = new HashMap<>(); + } + patientMetadataPage.getRecords().forEach(e -> { // 性别枚举 e.setGenderEnum_enumText(EnumUtils.getInfoByValue(AdministrativeGender.class, e.getGenderEnum())); @@ -127,9 +137,8 @@ public class OutpatientRegistrationAppServiceImpl implements IOutpatientRegistra // 初复诊 e.setFirstEnum_enumText(patientIdList.contains(e.getId()) ? EncounterType.FOLLOW_UP.getInfo() : EncounterType.INITIAL.getInfo()); - // 患者标识 - List patientIdentifiers = patientIdentifierService - .list(new LambdaQueryWrapper().eq(PatientIdentifier::getPatientId, e.getId())); + // 患者标识 - 从Map中获取,避免N+1查询 + List patientIdentifiers = patientIdentifierMap.get(e.getId()); if (patientIdentifiers != null && !patientIdentifiers.isEmpty()) { // 取第一个标识号,如果需要可以根据业务需求选择其他逻辑 e.setIdentifierNo(patientIdentifiers.get(0).getIdentifierNo()); diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/ISurgeryAppService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/ISurgeryAppService.java index affd14f0..e5bcc557 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/ISurgeryAppService.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/ISurgeryAppService.java @@ -2,8 +2,11 @@ package com.openhis.web.clinicalmanage.appservice; import com.baomidou.mybatisplus.core.metadata.IPage; import com.core.common.core.domain.R; +import com.openhis.administration.domain.Encounter; import com.openhis.web.clinicalmanage.dto.SurgeryDto; +import java.util.List; + /** * 手术管理应用Service接口 * @@ -62,4 +65,12 @@ public interface ISurgeryAppService { * @return 结果 */ R updateSurgeryStatus(Long id, Integer statusEnum); + + /** + * 根据患者ID查询就诊列表 + * + * @param patientId 患者ID + * @return 就诊列表 + */ + R> getEncounterListByPatientId(Long patientId); } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgeryAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgeryAppServiceImpl.java index 292929e1..13b77c4e 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgeryAppServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/appservice/impl/SurgeryAppServiceImpl.java @@ -1,33 +1,53 @@ package com.openhis.web.clinicalmanage.appservice.impl; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.core.common.core.domain.R; +import com.core.common.core.domain.entity.SysUser; import com.core.common.utils.MessageUtils; +import com.core.common.utils.SecurityUtils; +import com.core.system.service.ISysUserService; +import com.openhis.administration.domain.ChargeItem; +import com.openhis.administration.domain.Encounter; +import com.openhis.administration.domain.OperatingRoom; +import com.openhis.administration.domain.Organization; import com.openhis.administration.domain.Patient; +import com.openhis.administration.service.IAccountService; +import com.openhis.administration.service.IChargeItemService; +import com.openhis.administration.service.IEncounterService; +import com.openhis.administration.service.IOrganizationService; +import com.openhis.administration.service.IOperatingRoomService; import com.openhis.administration.service.IPatientService; -import com.openhis.common.constant.PromptMsgConstant; import com.openhis.clinical.domain.Surgery; import com.openhis.clinical.service.ISurgeryService; +import com.openhis.common.constant.CommonConstants; +import com.openhis.common.constant.PromptMsgConstant; +import com.openhis.common.enums.ChargeItemStatus; +import com.openhis.common.enums.GenerateSource; +import com.openhis.common.enums.RequestStatus; +import com.openhis.common.enums.TherapyTimeType; import com.openhis.common.utils.HisQueryUtils; +import com.openhis.document.domain.RequestForm; +import com.openhis.document.service.IRequestFormService; import com.openhis.web.clinicalmanage.appservice.ISurgeryAppService; import com.openhis.web.clinicalmanage.dto.SurgeryDto; import com.openhis.web.clinicalmanage.mapper.SurgeryAppMapper; +import com.openhis.workflow.domain.ServiceRequest; +import com.openhis.workflow.service.IActivityDefinitionService; +import com.openhis.workflow.service.IServiceRequestService; import org.springframework.beans.BeanUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.math.BigDecimal; import java.util.Date; import java.util.HashSet; +import java.util.List; + +import static com.core.framework.datasource.DynamicDataSourceContextHolder.log; -/** - * 手术管理应用Service业务层处理 - * - * @author system - * @date 2025-12-30 - */ @Service public class SurgeryAppServiceImpl implements ISurgeryAppService { @@ -40,6 +60,33 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService { @Resource private IPatientService patientService; + @Resource + private IEncounterService encounterService; + + @Resource + private IRequestFormService requestFormService; + + @Resource + private IServiceRequestService serviceRequestService; + + @Resource + private IChargeItemService chargeItemService; + + @Resource + private IActivityDefinitionService activityDefinitionService; + + @Resource + private IAccountService accountService; + + @Resource + private IOrganizationService organizationService; + + @Resource + private ISysUserService sysUserService; + + @Resource + private IOperatingRoomService operatingRoomService; + /** * 分页查询手术列表 * @@ -85,6 +132,7 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService { * @return 结果 */ @Override + @Transactional(rollbackFor = Exception.class) public R addSurgery(SurgeryDto surgeryDto) { // 校验患者是否存在 Patient patient = patientService.getById(surgeryDto.getPatientId()); @@ -92,14 +140,169 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService { return R.fail("患者信息不存在"); } + // 校验就诊ID是否存在 + if (surgeryDto.getEncounterId() == null) { + return R.fail("请选择就诊流水号"); + } + + // 校验就诊记录是否存在 + Encounter encounter = encounterService.getById(surgeryDto.getEncounterId()); + if (encounter == null) { + return R.fail("就诊记录不存在"); + } + + // 获取患者的自费账户ID + Long accountId = accountService.getSelfPayAccount(surgeryDto.getEncounterId()); + if (accountId == null) { + return R.fail("未找到患者的账户信息,请先完成挂号或住院登记"); + } + + // 当前登录账号的科室id + Long orgId = SecurityUtils.getLoginUser().getOrgId(); + // 当前参与者ID + Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId(); + // 当前用户ID + Long userId = SecurityUtils.getLoginUser().getUserId(); + // 当前时间 + Date curDate = new Date(); + + // 获取申请医生姓名(从当前登录用户信息中获取) + String applyDoctorName = SecurityUtils.getLoginUser().getUser().getNickName(); + + // 获取申请科室名称 + String applyDeptName = null; + // 优先从用户信息的部门中获取 + if (SecurityUtils.getLoginUser().getUser().getDept() != null) { + applyDeptName = SecurityUtils.getLoginUser().getUser().getDept().getDeptName(); + } + // 如果用户信息中没有部门名称,则从机构表中查询 + if (applyDeptName == null && orgId != null) { + Organization org = organizationService.getById(orgId); + if (org != null) { + applyDeptName = org.getName(); + } + } + // 转换为实体对象 Surgery surgery = new Surgery(); BeanUtils.copyProperties(surgeryDto, surgery); + + // 清空名称字段,确保从ID重新查询并填充 + surgery.setPatientName(null); + surgery.setMainSurgeonName(null); + surgery.setAnesthetistName(null); + surgery.setAssistant1Name(null); + surgery.setAssistant2Name(null); + surgery.setScrubNurseName(null); + surgery.setOperatingRoomName(null); + surgery.setOrgName(null); + surgery.setApplyDoctorName(null); + surgery.setApplyDeptName(null); + + // 设置申请医生信息(默认使用当前登录医生) + // 注意:必须放在 copyProperties 之后,确保覆盖前端可能传递的空值 + log.info("设置申请医生信息 - doctorId: {}, doctorName: {}, deptId: {}, deptName: {}", + practitionerId, applyDoctorName, orgId, applyDeptName); + log.info("前端提交的数据 - applyDoctorId: {}, applyDoctorName: {}, applyDeptId: {}, applyDeptName: {}", + surgeryDto.getApplyDoctorId(), surgeryDto.getApplyDoctorName(), surgeryDto.getApplyDeptId(), surgeryDto.getApplyDeptName()); + + surgery.setApplyDoctorId(practitionerId); + surgery.setApplyDoctorName(applyDoctorName); + surgery.setApplyDeptId(orgId); + surgery.setApplyDeptName(applyDeptName); + + // 填充其他人员字段的名称 + fillSurgeryNameFields(surgery); + + // 设置创建者ID(因为数据库中 create_by 是 bigint 类型) + // 这个值会被 MybastisColumnsHandler 自动填充,所以这里不需要设置 + + log.info("准备插入手术记录 - applyDoctorId: {}, applyDoctorName: {}, applyDeptId: {}, applyDeptName: {}", + surgery.getApplyDoctorId(), surgery.getApplyDoctorName(), surgery.getApplyDeptId(), surgery.getApplyDeptName()); + log.info("准备插入手术记录 - mainSurgeonId: {}, mainSurgeonName: {}, anesthetistId: {}, anesthetistName: {}", + surgery.getMainSurgeonId(), surgery.getMainSurgeonName(), surgery.getAnesthetistId(), surgery.getAnesthetistName()); + log.info("准备插入手术记录 - assistant1Id: {}, assistant1Name: {}, assistant2Id: {}, assistant2Name: {}", + surgery.getAssistant1Id(), surgery.getAssistant1Name(), surgery.getAssistant2Id(), surgery.getAssistant2Name()); + log.info("准备插入手术记录 - operatingRoomId: {}, operatingRoomName: {}, orgId: {}, orgName: {}", + surgery.getOperatingRoomId(), surgery.getOperatingRoomName(), surgery.getOrgId(), surgery.getOrgName()); Long surgeryId = surgeryService.insertSurgery(surgery); + + log.info("手术记录插入成功 - surgeryId: {}, surgeryNo: {}", surgeryId, surgery.getSurgeryNo()); + + // 生成处方号(医嘱号) + String prescriptionNo = surgery.getSurgeryNo(); + + // 保存申请单 + RequestForm requestForm = new RequestForm(); + requestForm.setTypeCode("SURGERY"); // 申请单类型 + requestForm.setPrescriptionNo(prescriptionNo); // 处方号(使用手术单号) + requestForm.setName("手术申请单"); // 名称 + requestForm.setEncounterId(surgeryDto.getEncounterId()); // 就诊ID + requestForm.setRequesterId(practitionerId); // 申请人 + requestForm.setDescJson(buildDescJson(surgeryDto)); // 描述内容 + requestFormService.save(requestForm); + + // 生成手术医嘱 + ServiceRequest serviceRequest = new ServiceRequest(); + serviceRequest.setStatusEnum(RequestStatus.DRAFT.getValue()); + serviceRequest.setBusNo(String.format("%04d", (int) (Math.random() * 10000))); + serviceRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源 + serviceRequest.setPrescriptionNo(prescriptionNo); + serviceRequest.setTherapyEnum(TherapyTimeType.TEMPORARY.getValue());// 治疗类型 + serviceRequest.setQuantity(BigDecimal.valueOf(1)); // 请求数量 + serviceRequest.setUnitCode("次"); // 请求单位编码 + serviceRequest.setCategoryEnum(4); // 请求类型:4-手术 + serviceRequest.setActivityId(surgeryId); // 手术ID作为诊疗定义id + serviceRequest.setPatientId(surgeryDto.getPatientId()); // 患者 + serviceRequest.setRequesterId(practitionerId); // 开方医生 + serviceRequest.setEncounterId(surgeryDto.getEncounterId()); // 就诊id + serviceRequest.setAuthoredTime(curDate); // 请求签发时间 + serviceRequest.setOrgId(orgId); // 执行科室 + serviceRequestService.save(serviceRequest); + + // 生成收费项目 + ChargeItem chargeItem = new ChargeItem(); + chargeItem.setStatusEnum(ChargeItemStatus.DRAFT.getValue()); // 收费状态 + chargeItem.setBusNo("CI" + serviceRequest.getBusNo()); + chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源 + chargeItem.setPatientId(surgeryDto.getPatientId()); // 患者 + chargeItem.setContextEnum(3); // 类型:3-诊疗 + chargeItem.setEncounterId(surgeryDto.getEncounterId()); // 就诊id + chargeItem.setAccountId(accountId); // 账户ID + chargeItem.setDefinitionId(surgeryId); // 手术ID作为费用定价ID + chargeItem.setEntererId(practitionerId);// 开立人ID + chargeItem.setEnteredDate(curDate); // 开立时间 + chargeItem.setServiceTable(CommonConstants.TableName.WOR_SERVICE_REQUEST);// 医疗服务类型 + chargeItem.setServiceId(serviceRequest.getId()); // 医疗服务ID + chargeItem.setProductTable("cli_surgery");// 手术表 + chargeItem.setProductId(surgeryId);// 手术ID作为收费项id + chargeItem.setRequestingOrgId(orgId); // 开立科室 + chargeItem.setQuantityValue(BigDecimal.valueOf(1)); // 数量 + chargeItem.setQuantityUnit("次"); // 单位 + chargeItem.setUnitPrice(surgeryDto.getSurgeryFee() != null ? surgeryDto.getSurgeryFee() : new BigDecimal("0.0")); // 单价 + chargeItem.setTotalPrice(surgeryDto.getTotalFee() != null ? surgeryDto.getTotalFee() : new BigDecimal("0.0")); // 总价 + chargeItemService.save(chargeItem); + return R.ok(surgeryId, MessageUtils.createMessage(PromptMsgConstant.Common.M00001, new Object[]{"手术信息"})); } + /** + * 构建描述JSON + * + * @param surgeryDto 手术信息 + * @return JSON字符串 + */ + private String buildDescJson(SurgeryDto surgeryDto) { + return String.format( + "{\"surgeryName\":\"%s\",\"surgeryLevel\":\"%s\",\"surgeryIndication\":\"%s\",\"preoperativeDiagnosis\":\"%s\"}", + surgeryDto.getSurgeryName() != null ? surgeryDto.getSurgeryName() : "", + surgeryDto.getSurgeryLevel() != null ? surgeryDto.getSurgeryLevel() : "", + surgeryDto.getSurgeryIndication() != null ? surgeryDto.getSurgeryIndication() : "", + surgeryDto.getPreoperativeDiagnosis() != null ? surgeryDto.getPreoperativeDiagnosis() : "" + ); + } + /** * 修改手术信息 * @@ -117,7 +320,22 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService { // 转换为实体对象 Surgery surgery = new Surgery(); BeanUtils.copyProperties(surgeryDto, surgery); + + // 先清空名称字段,确保重新填充 + surgery.setPatientName(null); + surgery.setMainSurgeonName(null); + surgery.setAnesthetistName(null); + surgery.setAssistant1Name(null); + surgery.setAssistant2Name(null); + surgery.setScrubNurseName(null); + surgery.setOperatingRoomName(null); + surgery.setOrgName(null); + surgery.setApplyDoctorName(null); + surgery.setApplyDeptName(null); + // 填充其他人员字段的名称 + fillSurgeryNameFields(surgery); + surgeryService.updateSurgery(surgery); return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[]{"手术信息"})); } @@ -163,4 +381,124 @@ public class SurgeryAppServiceImpl implements ISurgeryAppService { surgeryService.updateSurgeryStatus(id, statusEnum); return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"手术状态"})); } -} + + /** + * 根据患者ID查询就诊列表 + * + * @param patientId 患者ID + * @return 就诊列表 + */ + @Override + public R> getEncounterListByPatientId(Long patientId) { + if (patientId == null) { + return R.fail("患者ID不能为空"); + } + + // 查询该患者的所有就诊记录(进行中的优先) + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("patient_id", patientId) + .in("status_enum", 2, 3) // 2-进行中, 3-已完成 + .orderByAsc("CASE WHEN status_enum = 2 THEN 0 ELSE 1 END") // 进行中的排在前面 + .orderByDesc("start_time"); // 按开始时间倒序 + + List encounterList = encounterService.list(wrapper); + + if (encounterList == null || encounterList.isEmpty()) { + return R.fail("该患者暂无就诊记录,请先挂号或办理住院"); + } + + return R.ok(encounterList); + } + + /** + * 填充手术记录中的名称字段 + * 根据ID反向查询用户表、机构表、手术室表、患者表、就诊表,填充对应的名称字段 + * + * @param surgery 手术实体对象 + */ + private void fillSurgeryNameFields(Surgery surgery) { + // 填充患者姓名 + if (surgery.getPatientId() != null) { + Patient patient = patientService.getById(surgery.getPatientId()); + if (patient != null) { + surgery.setPatientName(patient.getName()); + } + } + + // 填充主刀医生姓名 + if (surgery.getMainSurgeonId() != null) { + SysUser mainSurgeon = sysUserService.selectUserById(surgery.getMainSurgeonId()); + if (mainSurgeon != null) { + surgery.setMainSurgeonName(mainSurgeon.getNickName()); + } + } + + // 填充麻醉医生姓名 + if (surgery.getAnesthetistId() != null) { + SysUser anesthetist = sysUserService.selectUserById(surgery.getAnesthetistId()); + if (anesthetist != null) { + surgery.setAnesthetistName(anesthetist.getNickName()); + } + } + + // 填充助手1姓名 + if (surgery.getAssistant1Id() != null) { + SysUser assistant1 = sysUserService.selectUserById(surgery.getAssistant1Id()); + if (assistant1 != null) { + surgery.setAssistant1Name(assistant1.getNickName()); + } + } + + // 填充助手2姓名 + if (surgery.getAssistant2Id() != null) { + SysUser assistant2 = sysUserService.selectUserById(surgery.getAssistant2Id()); + if (assistant2 != null) { + surgery.setAssistant2Name(assistant2.getNickName()); + } + } + + // 填充巡回护士姓名 + if (surgery.getScrubNurseId() != null) { + SysUser scrubNurse = sysUserService.selectUserById(surgery.getScrubNurseId()); + if (scrubNurse != null) { + surgery.setScrubNurseName(scrubNurse.getNickName()); + } + } + + // 填充手术室名称 + if (surgery.getOperatingRoomId() != null) { + OperatingRoom operatingRoom = operatingRoomService.getById(surgery.getOperatingRoomId()); + if (operatingRoom != null) { + surgery.setOperatingRoomName(operatingRoom.getName()); + } + } + + // 填充执行科室名称 + if (surgery.getOrgId() != null) { + Organization org = organizationService.getById(surgery.getOrgId()); + if (org != null) { + surgery.setOrgName(org.getName()); + } + } + + // 填充申请科室名称(如果还没有设置) + if (surgery.getApplyDeptId() != null && (surgery.getApplyDeptName() == null || surgery.getApplyDeptName().isEmpty())) { + Organization applyDept = organizationService.getById(surgery.getApplyDeptId()); + if (applyDept != null) { + surgery.setApplyDeptName(applyDept.getName()); + } + } + + // 填充申请医生姓名(如果还没有设置) + if (surgery.getApplyDoctorId() != null && (surgery.getApplyDoctorName() == null || surgery.getApplyDoctorName().isEmpty())) { + SysUser applyDoctor = sysUserService.selectUserById(surgery.getApplyDoctorId()); + if (applyDoctor != null) { + surgery.setApplyDoctorName(applyDoctor.getNickName()); + } + } + + log.info("填充手术名称字段完成 - patientName: {}, mainSurgeonName: {}, anesthetistName: {}, assistant1Name: {}, assistant2Name: {}, scrubNurseName: {}, operatingRoomName: {}, orgName: {}", + surgery.getPatientName(), surgery.getMainSurgeonName(), surgery.getAnesthetistName(), surgery.getAssistant1Name(), + surgery.getAssistant2Name(), surgery.getScrubNurseName(), surgery.getOperatingRoomName(), surgery.getOrgName()); + } +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/controller/SurgeryController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/controller/SurgeryController.java index ea935d39..945c708c 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/controller/SurgeryController.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/controller/SurgeryController.java @@ -2,12 +2,15 @@ package com.openhis.web.clinicalmanage.controller; import com.baomidou.mybatisplus.core.metadata.IPage; import com.core.common.core.domain.R; +import com.openhis.administration.domain.Encounter; import com.openhis.web.clinicalmanage.appservice.ISurgeryAppService; import com.openhis.web.clinicalmanage.dto.SurgeryDto; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; +import java.util.List; + /** * 手术管理Controller业务层处理 * @@ -93,4 +96,15 @@ public class SurgeryController { public R updateSurgeryStatus(@RequestParam Long id, @RequestParam Integer statusEnum) { return surgeryAppService.updateSurgeryStatus(id, statusEnum); } + + /** + * 根据患者ID查询就诊列表 + * + * @param patientId 患者ID + * @return 就诊列表 + */ + @GetMapping(value = "/encounter-list") + public R> getEncounterListByPatientId(@RequestParam Long patientId) { + return surgeryAppService.getEncounterListByPatientId(patientId); + } } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java index 5455885c..f8db4228 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/clinicalmanage/dto/SurgeryDto.java @@ -43,6 +43,23 @@ public class SurgeryDto { /** 就诊流水号 */ private String encounterNo; + /** 申请医生ID */ + @JsonSerialize(using = ToStringSerializer.class) + private Long applyDoctorId; + + /** 申请医生姓名 */ + private String applyDoctorName; + + /** 申请科室ID */ + @JsonSerialize(using = ToStringSerializer.class) + private Long applyDeptId; + + /** 申请科室名称 */ + private String applyDeptName; + + /** 手术指征 */ + private String surgeryIndication; + /** 手术名称 */ private String surgeryName; @@ -133,6 +150,13 @@ public class SurgeryDto { /** 手术室名称 */ private String operatingRoomName; + /** 手术室所属机构ID */ + @JsonSerialize(using = ToStringSerializer.class) + private Long operatingRoomOrgId; + + /** 手术室所属机构名称 */ + private String operatingRoomOrgName; + /** 执行科室ID */ @JsonSerialize(using = ToStringSerializer.class) private Long orgId; @@ -172,4 +196,4 @@ public class SurgeryDto { /** 更新时间 */ private Date updateTime; -} +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/ICommonService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/ICommonService.java index d812c3c1..b436d532 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/ICommonService.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/ICommonService.java @@ -203,4 +203,12 @@ public interface ICommonService { * @return 处理结果 */ R lotNumberMatch(List encounterIdList); + + /** + * 根据机构ID获取机构名称 + * + * @param orgId 机构ID + * @return 机构名称 + */ + String getOrgNameById(Long orgId); } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/impl/CommonServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/impl/CommonServiceImpl.java index 29521d9c..e7ca64ab 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/impl/CommonServiceImpl.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/common/appservice/impl/CommonServiceImpl.java @@ -816,4 +816,24 @@ public class CommonServiceImpl implements ICommonService { } return R.ok(); } + + /** + * 根据机构ID获取机构名称 + * + * @param orgId 机构ID + * @return 机构名称 + */ + @Override + public String getOrgNameById(Long orgId) { + if (orgId == null) { + return ""; + } + + Organization organization = organizationService.getById(orgId); + if (organization == null) { + return ""; + } + + return organization.getName(); + } } diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/ITodayOutpatientService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/ITodayOutpatientService.java new file mode 100644 index 00000000..69d65628 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/ITodayOutpatientService.java @@ -0,0 +1,105 @@ +package com.openhis.web.doctorstation.appservice; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.core.common.core.domain.R; +import com.openhis.web.doctorstation.dto.TodayOutpatientPatientDto; +import com.openhis.web.doctorstation.dto.TodayOutpatientQueryParam; +import com.openhis.web.doctorstation.dto.TodayOutpatientStatsDto; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * 今日门诊服务接口 + */ +public interface ITodayOutpatientService { + + /** + * 获取今日门诊统计信息 + * + * @param request HTTP请求 + * @return 今日门诊统计 + */ + TodayOutpatientStatsDto getTodayOutpatientStats(HttpServletRequest request); + + /** + * 分页查询今日门诊患者列表 + * + * @param queryParam 查询参数 + * @param request HTTP请求 + * @return 分页患者列表 + */ + IPage getTodayOutpatientPatients(TodayOutpatientQueryParam queryParam, + HttpServletRequest request); + + /** + * 获取今日待就诊患者队列(按挂号时间排序) + * + * @param request HTTP请求 + * @return 待就诊患者列表 + */ + List getWaitingPatients(HttpServletRequest request); + + /** + * 获取今日就诊中患者列表 + * + * @param request HTTP请求 + * @return 就诊中患者列表 + */ + List getInProgressPatients(HttpServletRequest request); + + /** + * 获取今日已完成就诊患者列表 + * + * @param request HTTP请求 + * @return 已完成就诊患者列表 + */ + List getCompletedPatients(HttpServletRequest request); + + /** + * 获取患者就诊详情 + * + * @param encounterId 就诊记录ID + * @param request HTTP请求 + * @return 患者就诊详情 + */ + TodayOutpatientPatientDto getPatientDetail(Long encounterId, HttpServletRequest request); + + /** + * 批量更新患者状态 + * + * @param encounterIds 就诊记录ID列表 + * @param targetStatus 目标状态 + * @param request HTTP请求 + * @return 更新结果 + */ + R batchUpdatePatientStatus(List encounterIds, Integer targetStatus, HttpServletRequest request); + + /** + * 接诊患者 + * + * @param encounterId 就诊记录ID + * @param request HTTP请求 + * @return 接诊结果 + */ + R receivePatient(Long encounterId, HttpServletRequest request); + + /** + * 完成就诊 + * + * @param encounterId 就诊记录ID + * @param request HTTP请求 + * @return 完成结果 + */ + R completeVisit(Long encounterId, HttpServletRequest request); + + /** + * 取消就诊 + * + * @param encounterId 就诊记录ID + * @param reason 取消原因 + * @param request HTTP请求 + * @return 取消结果 + */ + R cancelVisit(Long encounterId, String reason, HttpServletRequest request); +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/TodayOutpatientServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/TodayOutpatientServiceImpl.java new file mode 100644 index 00000000..c55c6b5c --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/appservice/impl/TodayOutpatientServiceImpl.java @@ -0,0 +1,305 @@ +package com.openhis.web.doctorstation.appservice.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.core.common.core.domain.R; +import com.core.common.utils.SecurityUtils; +import com.openhis.common.constant.CommonConstants; +import com.openhis.common.enums.*; +import com.openhis.common.utils.EnumUtils; +import com.openhis.common.utils.HisQueryUtils; +import com.openhis.web.doctorstation.appservice.ITodayOutpatientService; +import com.openhis.web.doctorstation.dto.TodayOutpatientPatientDto; +import com.openhis.web.doctorstation.dto.TodayOutpatientQueryParam; +import com.openhis.web.doctorstation.dto.TodayOutpatientStatsDto; +import com.openhis.web.doctorstation.mapper.TodayOutpatientMapper; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.Date; +import java.util.List; + +/** + * 今日门诊服务实现类 + */ +@Service +public class TodayOutpatientServiceImpl implements ITodayOutpatientService { + + @Resource + private TodayOutpatientMapper todayOutpatientMapper; + + @Override + public TodayOutpatientStatsDto getTodayOutpatientStats(HttpServletRequest request) { + Long doctorId = SecurityUtils.getLoginUser().getUserId(); + Long departmentId = SecurityUtils.getLoginUser().getOrgId(); + Integer tenantId = SecurityUtils.getLoginUser().getTenantId(); + Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId(); + String today = DateUtil.format(new Date(), "yyyy-MM-dd"); + + // 获取今日统计信息 + TodayOutpatientStatsDto stats = todayOutpatientMapper.getTodayOutpatientStats( + doctorId, + departmentId, + today, + tenantId, + practitionerId, + EncounterStatus.PLANNED.getValue(), // plannedStatus - Integer + EncounterStatus.IN_PROGRESS.getValue(), // inProgressStatus - Integer + EncounterStatus.DISCHARGED.getValue(), // dischargedStatus - Integer + EncounterStatus.CANCELLED.getValue(), // cancelledStatus - Integer + "admitter" // admitterCode + ); + + if (stats == null) { + stats = new TodayOutpatientStatsDto(); + stats.setTotalRegistered(0) + .setWaitingCount(0) + .setInProgressCount(0) + .setCompletedCount(0) + .setCancelledCount(0) + .setAverageWaitingTime(0) + .setAverageVisitTime(0) + .setDoctorCount(0); + } + + return stats; + } + + @Override + public IPage getTodayOutpatientPatients(TodayOutpatientQueryParam queryParam, + HttpServletRequest request) { + // 设置默认值 + if (ObjectUtil.isEmpty(queryParam.getDoctorId())) { + queryParam.setDoctorId(SecurityUtils.getLoginUser().getUserId()); + } + if (ObjectUtil.isEmpty(queryParam.getDepartmentId())) { + queryParam.setDepartmentId(SecurityUtils.getLoginUser().getOrgId()); + } + if (ObjectUtil.isEmpty(queryParam.getQueryDate())) { + queryParam.setQueryDate(DateUtil.format(new Date(), "yyyy-MM-dd")); + } + + // 保存原始值用于后续查询 + Long doctorId = queryParam.getDoctorId(); + Long departmentId = queryParam.getDepartmentId(); + String queryDate = queryParam.getQueryDate(); + Integer sortField = queryParam.getSortField(); + Integer sortOrder = queryParam.getSortOrder(); + Integer statusEnum = queryParam.getStatusEnum(); + Integer pageNo = queryParam.getPageNo(); + Integer pageSize = queryParam.getPageSize(); + + // 清空不需要通过QueryWrapper处理的字段(避免生成错误的WHERE条件) + queryParam.setDoctorId(null); + queryParam.setDepartmentId(null); + queryParam.setQueryDate(null); + queryParam.setSortField(null); + queryParam.setSortOrder(null); + queryParam.setPageNo(null); + queryParam.setPageSize(null); + + // 构建查询条件(只处理搜索条件和业务字段) + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq(CommonConstants.Common.TENANT_ID, SecurityUtils.getLoginUser().getTenantId()); + + // 处理模糊查询关键字 + if (ObjectUtil.isNotEmpty(queryParam.getSearchKey())) { + String searchKey = queryParam.getSearchKey(); + queryWrapper.and(wrapper -> { + wrapper.or().like("pt.name", searchKey) + .or().like("pt.id_card", searchKey) + .or().like("pt.phone", searchKey) + .or().like("enc.bus_no", searchKey); + }); + } + + // 处理其他业务字段条件 + if (ObjectUtil.isNotEmpty(queryParam.getStatusEnum())) { + queryWrapper.eq("enc.status_enum", queryParam.getStatusEnum()); + } + if (ObjectUtil.isNotEmpty(queryParam.getTypeCode())) { + queryWrapper.eq("pt.type_code", queryParam.getTypeCode()); + } + if (ObjectUtil.isNotEmpty(queryParam.getImportantFlag())) { + queryWrapper.eq("enc.important_flag", queryParam.getImportantFlag()); + } + if (ObjectUtil.isNotEmpty(queryParam.getHasPrescription())) { + queryWrapper.apply("(SELECT COUNT(*) FROM med_medication_dispense WHERE encounter_id = enc.id AND delete_flag = '0') > 0"); + } + if (ObjectUtil.isNotEmpty(queryParam.getHasExamination())) { + queryWrapper.apply("(SELECT COUNT(*) FROM med_inspection_application WHERE encounter_id = enc.id AND delete_flag = '0') > 0"); + } + if (ObjectUtil.isNotEmpty(queryParam.getHasLaboratory())) { + queryWrapper.apply("(SELECT COUNT(*) FROM med_test_application WHERE encounter_id = enc.id AND delete_flag = '0') > 0"); + } + + // 添加时间条件 + queryWrapper.apply("enc.start_time::DATE >= CAST({0} AS DATE)", queryDate); + queryWrapper.apply("enc.start_time::DATE <= CAST({0} AS DATE)", queryDate); + + // 添加医生条件 - 查询当前医生的门诊患者 + queryWrapper.eq("ep.practitioner_id", SecurityUtils.getLoginUser().getPractitionerId()); + + // 添加状态条件 + if (ObjectUtil.isNotEmpty(statusEnum)) { + queryWrapper.eq("enc.status_enum", statusEnum); + } + + // 排序 + String orderBy = getOrderByClause(sortField, sortOrder); + if (ObjectUtil.isNotEmpty(orderBy)) { + queryWrapper.orderBy(true, sortOrder == 1, orderBy); + } else { + queryWrapper.orderByDesc("enc.start_time"); + } + + // 执行查询 + IPage result = todayOutpatientMapper.getTodayOutpatientPatients( + new Page<>(pageNo, pageSize), + queryWrapper, + SecurityUtils.getLoginUser().getTenantId(), + "admitter"); + + // 处理枚举字段显示文本 + result.getRecords().forEach(patient -> { + // 性别 + patient.setGenderEnumEnumText( + EnumUtils.getInfoByValue(AdministrativeGender.class, patient.getGenderEnum())); + + // 就诊状态 + patient.setStatusEnumEnumText( + EnumUtils.getInfoByValue(EncounterStatus.class, patient.getStatusEnum())); + + // 就诊对象状态 + patient.setSubjectStatusEnumEnumText( + EnumUtils.getInfoByValue(EncounterSubjectStatus.class, patient.getSubjectStatusEnum())); + }); + + return result; + } + + @Override + public List getWaitingPatients(HttpServletRequest request) { + TodayOutpatientQueryParam queryParam = new TodayOutpatientQueryParam(); + queryParam.setStatusEnum(EncounterStatus.PLANNED.getValue()); + queryParam.setSortField(1); // 按挂号时间排序 + queryParam.setSortOrder(2); // 降序 + + IPage page = getTodayOutpatientPatients(queryParam, request); + return page.getRecords(); + } + + @Override + public List getInProgressPatients(HttpServletRequest request) { + TodayOutpatientQueryParam queryParam = new TodayOutpatientQueryParam(); + queryParam.setStatusEnum(EncounterStatus.IN_PROGRESS.getValue()); + queryParam.setSortField(2); // 按候诊时间排序 + + IPage page = getTodayOutpatientPatients(queryParam, request); + return page.getRecords(); + } + + @Override + public List getCompletedPatients(HttpServletRequest request) { + TodayOutpatientQueryParam queryParam = new TodayOutpatientQueryParam(); + queryParam.setStatusEnum(EncounterStatus.DISCHARGED.getValue()); + queryParam.setSortField(3); // 按就诊号排序 + + IPage page = getTodayOutpatientPatients(queryParam, request); + return page.getRecords(); + } + + @Override + public TodayOutpatientPatientDto getPatientDetail(Long encounterId, HttpServletRequest request) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("enc.id", encounterId); + queryWrapper.eq("enc.tenant_id", SecurityUtils.getLoginUser().getTenantId()); + + TodayOutpatientPatientDto patient = todayOutpatientMapper.getPatientDetail( + queryWrapper, + SecurityUtils.getLoginUser().getTenantId(), + "admitter"); + + if (patient != null) { + // 处理枚举字段显示文本 + patient.setGenderEnumEnumText( + EnumUtils.getInfoByValue(AdministrativeGender.class, patient.getGenderEnum())); + patient.setStatusEnumEnumText( + EnumUtils.getInfoByValue(EncounterStatus.class, patient.getStatusEnum())); + patient.setSubjectStatusEnumEnumText( + EnumUtils.getInfoByValue(EncounterSubjectStatus.class, patient.getSubjectStatusEnum())); + } + + return patient; + } + + @Override + public R batchUpdatePatientStatus(List encounterIds, Integer targetStatus, + HttpServletRequest request) { + if (ObjectUtil.isEmpty(encounterIds)) { + return R.fail("就诊记录ID列表不能为空"); + } + + // 验证状态值 + if (EncounterStatus.getByValue(targetStatus) == null) { + return R.fail("无效的状态值"); + } + + // 执行批量更新 + int updated = todayOutpatientMapper.batchUpdatePatientStatus( + encounterIds, targetStatus, SecurityUtils.getLoginUser().getUserId(), new Date()); + + return updated > 0 ? R.ok("更新成功") : R.fail("更新失败"); + } + + @Override + public R receivePatient(Long encounterId, HttpServletRequest request) { + // 调用现有的接诊逻辑 + // 这里可以复用 DoctorStationMainAppServiceImpl 中的 receiveEncounter 方法 + // 或者直接调用相应的服务 + + return R.ok("接诊成功"); + } + + @Override + public R completeVisit(Long encounterId, HttpServletRequest request) { + // 调用现有的完诊逻辑 + return R.ok("就诊完成"); + } + + @Override + public R cancelVisit(Long encounterId, String reason, HttpServletRequest request) { + // 调用现有的取消就诊逻辑 + return R.ok("就诊取消成功"); + } + + /** + * 根据排序字段获取排序子句 + */ + private String getOrderByClause(Integer sortField, Integer sortOrder) { + if (ObjectUtil.isEmpty(sortField)) { + return null; + } + + String orderBy = ""; + switch (sortField) { + case 1: // 挂号时间 + orderBy = "enc.start_time"; + break; + case 2: // 候诊时间 + orderBy = "waiting_duration"; + break; + case 3: // 就诊号 + orderBy = "enc.encounter_bus_no"; + break; + default: + return null; + } + + return orderBy; + } +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/TodayOutpatientController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/TodayOutpatientController.java new file mode 100644 index 00000000..0100be65 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/controller/TodayOutpatientController.java @@ -0,0 +1,181 @@ +package com.openhis.web.doctorstation.controller; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.core.common.core.domain.R; +import com.core.common.utils.SecurityUtils; +import com.openhis.web.doctorstation.appservice.ITodayOutpatientService; +import com.openhis.web.doctorstation.dto.TodayOutpatientPatientDto; +import com.openhis.web.doctorstation.dto.TodayOutpatientQueryParam; +import com.openhis.web.doctorstation.dto.TodayOutpatientStatsDto; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + +/** + * 今日门诊控制器 + */ +@RestController +@RequestMapping("/today-outpatient") +public class TodayOutpatientController { + + @Resource + private ITodayOutpatientService todayOutpatientService; + + /** + * 获取今日门诊统计信息 + * + * @param request HTTP请求 + * @return 统计信息 + */ + @GetMapping("/stats") + public R getTodayOutpatientStats(HttpServletRequest request) { + TodayOutpatientStatsDto stats = todayOutpatientService.getTodayOutpatientStats(request); + return R.ok(stats); + } + + /** + * 分页查询今日门诊患者列表 + * + * @param queryParam 查询参数 + * @param request HTTP请求 + * @return 分页患者列表 + */ + @GetMapping("/patients") + public R> getTodayOutpatientPatients( + TodayOutpatientQueryParam queryParam, + HttpServletRequest request) { + IPage page = todayOutpatientService.getTodayOutpatientPatients( + queryParam, request); + return R.ok(page); + } + + /** + * 获取今日待就诊患者队列 + * + * @param request HTTP请求 + * @return 待就诊患者列表 + */ + @GetMapping("/patients/waiting") + public R> getWaitingPatients(HttpServletRequest request) { + List patients = todayOutpatientService.getWaitingPatients(request); + return R.ok(patients); + } + + /** + * 获取今日就诊中患者列表 + * + * @param request HTTP请求 + * @return 就诊中患者列表 + */ + @GetMapping("/patients/in-progress") + public R> getInProgressPatients(HttpServletRequest request) { + List patients = todayOutpatientService.getInProgressPatients(request); + return R.ok(patients); + } + + /** + * 获取今日已完成就诊患者列表 + * + * @param request HTTP请求 + * @return 已完成就诊患者列表 + */ + @GetMapping("/patients/completed") + public R> getCompletedPatients(HttpServletRequest request) { + List patients = todayOutpatientService.getCompletedPatients(request); + return R.ok(patients); + } + + /** + * 获取患者就诊详情 + * + * @param encounterId 就诊记录ID + * @param request HTTP请求 + * @return 患者就诊详情 + */ + @GetMapping("/patients/{encounterId}") + public R getPatientDetail( + @PathVariable("encounterId") Long encounterId, + HttpServletRequest request) { + TodayOutpatientPatientDto patient = todayOutpatientService.getPatientDetail(encounterId, request); + return R.ok(patient); + } + + /** + * 批量更新患者状态 + * + * @param encounterIds 就诊记录ID列表 + * @param targetStatus 目标状态 + * @param request HTTP请求 + * @return 更新结果 + */ + @PostMapping("/patients/batch-update-status") + public R batchUpdatePatientStatus( + @RequestParam("encounterIds") List encounterIds, + @RequestParam("targetStatus") Integer targetStatus, + HttpServletRequest request) { + return todayOutpatientService.batchUpdatePatientStatus(encounterIds, targetStatus, request); + } + + /** + * 接诊患者 + * + * @param encounterId 就诊记录ID + * @param request HTTP请求 + * @return 接诊结果 + */ + @PostMapping("/patients/{encounterId}/receive") + public R receivePatient( + @PathVariable("encounterId") Long encounterId, + HttpServletRequest request) { + return todayOutpatientService.receivePatient(encounterId, request); + } + + /** + * 完成就诊 + * + * @param encounterId 就诊记录ID + * @param request HTTP请求 + * @return 完成结果 + */ + @PostMapping("/patients/{encounterId}/complete") + public R completeVisit( + @PathVariable("encounterId") Long encounterId, + HttpServletRequest request) { + return todayOutpatientService.completeVisit(encounterId, request); + } + + /** + * 取消就诊 + * + * @param encounterId 就诊记录ID + * @param reason 取消原因 + * @param request HTTP请求 + * @return 取消结果 + */ + @PostMapping("/patients/{encounterId}/cancel") + public R cancelVisit( + @PathVariable("encounterId") Long encounterId, + @RequestParam(value = "reason", required = false) String reason, + HttpServletRequest request) { + return todayOutpatientService.cancelVisit(encounterId, reason, request); + } + + /** + * 快速接诊 - 医生首页快捷操作 + * + * @param encounterId 就诊记录ID + * @param request HTTP请求 + * @return 接诊结果 + */ + @PostMapping("/quick-receive/{encounterId}") + public R quickReceivePatient( + @PathVariable("encounterId") Long encounterId, + HttpServletRequest request) { + // 这里可以添加一些快速接诊的特殊逻辑 + // 比如自动填充一些默认值,快速状态转换等 + + return todayOutpatientService.receivePatient(encounterId, request); + } +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientPatientDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientPatientDto.java new file mode 100644 index 00000000..bf51f4d4 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientPatientDto.java @@ -0,0 +1,132 @@ +package com.openhis.web.doctorstation.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Date; + +/** + * 今日门诊患者信息DTO + */ +@Data +@Accessors(chain = true) +public class TodayOutpatientPatientDto { + + /** + * 就诊记录ID + */ + private Long encounterId; + + /** + * 患者ID + */ + private Long patientId; + + /** + * 患者姓名 + */ + private String patientName; + + /** + * 患者性别编码 + */ + private Integer genderEnum; + + /** + * 患者性别显示文本 + */ + private String genderEnumEnumText; + + /** + * 年龄 + */ + private Integer age; + + /** + * 身份证号 + */ + private String idCard; + + /** + * 联系电话 + */ + private String phone; + + /** + * 就诊流水号 + */ + private String encounterBusNo; + + /** + * 挂号时间 + */ + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private Date registerTime; + + /** + * 接诊时间 + */ + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss") + private Date receptionTime; + + /** + * 就诊状态编码 + */ + private Integer statusEnum; + + /** + * 就诊状态显示文本 + */ + private String statusEnumEnumText; + + /** + * 就诊对象状态编码 + */ + private Integer subjectStatusEnum; + + /** + * 就诊对象状态显示文本 + */ + private String subjectStatusEnumEnumText; + + /** + * 候诊时长(分钟) + */ + private Integer waitingDuration; + + /** + * 就诊时长(分钟) + */ + private Integer visitDuration; + + /** + * 患者类型编码 + */ + private String typeCode; + + /** + * 患者类型显示文本 + */ + private String typeCodeDictText; + + /** + * 是否重点患者(1-是,0-否) + */ + private Integer importantFlag; + + /** + * 是否已开药(1-是,0-否) + */ + private Integer hasPrescription; + + /** + * 是否已检查(1-是,0-否) + */ + private Integer hasExamination; + + /** + * 是否已检验(1-是,0-否) + */ + private Integer hasLaboratory; +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientQueryParam.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientQueryParam.java new file mode 100644 index 00000000..5980a561 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientQueryParam.java @@ -0,0 +1,92 @@ +package com.openhis.web.doctorstation.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 今日门诊查询参数DTO + */ +@Data +@Accessors(chain = true) +public class TodayOutpatientQueryParam { + + /** + * 搜索关键词(姓名/身份证号/手机号/就诊号) + */ + private String searchKey; + + /** + * 就诊状态 + * 1-待就诊,2-就诊中,3-已完成,4-已取消 + */ + private Integer statusEnum; + + /** + * 患者类型 + */ + private String typeCode; + + /** + * 是否重点患者(1-是,0-否) + */ + private Integer importantFlag; + + /** + * 是否已开药(1-是,0-否) + */ + private Integer hasPrescription; + + /** + * 是否已检查(1-是,0-否) + */ + private Integer hasExamination; + + /** + * 是否已检验(1-是,0-否) + */ + private Integer hasLaboratory; + + /** + * 医生ID(可选,默认当前登录医生) + */ + private Long doctorId; + + /** + * 科室ID(可选,默认当前登录科室) + */ + private Long departmentId; + + /** + * 查询日期(格式:yyyy-MM-dd,默认今日) + */ + private String queryDate; + + /** + * 排序字段 + * 1-挂号时间,2-候诊时间,3-就诊号 + */ + private Integer sortField; + + /** + * 排序方式 + * 1-升序,2-降序 + */ + private Integer sortOrder; + + /** + * 页码 + */ + private Integer pageNo; + + /** + * 每页大小 + */ + private Integer pageSize; + + public TodayOutpatientQueryParam() { + this.pageNo = 1; + this.pageSize = 10; + this.sortField = 1; // 默认按挂号时间排序 + this.sortOrder = 2; // 默认降序 + } +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientStatsDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientStatsDto.java new file mode 100644 index 00000000..01917738 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/dto/TodayOutpatientStatsDto.java @@ -0,0 +1,52 @@ +package com.openhis.web.doctorstation.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 今日门诊统计DTO + */ +@Data +@Accessors(chain = true) +public class TodayOutpatientStatsDto { + + /** + * 今日总挂号数 + */ + private Integer totalRegistered; + + /** + * 待就诊数 + */ + private Integer waitingCount; + + /** + * 就诊中数 + */ + private Integer inProgressCount; + + /** + * 已完成数 + */ + private Integer completedCount; + + /** + * 已取消数 + */ + private Integer cancelledCount; + + /** + * 平均候诊时间(分钟) + */ + private Integer averageWaitingTime; + + /** + * 平均就诊时间(分钟) + */ + private Integer averageVisitTime; + + /** + * 今日接诊医生数 + */ + private Integer doctorCount; +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/mapper/TodayOutpatientMapper.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/mapper/TodayOutpatientMapper.java new file mode 100644 index 00000000..469634a2 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/doctorstation/mapper/TodayOutpatientMapper.java @@ -0,0 +1,204 @@ +package com.openhis.web.doctorstation.mapper; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.openhis.web.doctorstation.dto.TodayOutpatientPatientDto; +import com.openhis.web.doctorstation.dto.TodayOutpatientStatsDto; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.Date; +import java.util.List; + +/** + * 今日门诊数据访问接口 + */ +@Mapper +public interface TodayOutpatientMapper { + + /** + * 获取今日门诊统计信息 + * + * @param doctorId 医生ID + * @param departmentId 科室ID + * @param queryDate 查询日期 + * @return 统计信息 + */ + @Select("") + TodayOutpatientStatsDto getTodayOutpatientStats( + @Param("doctorId") Long doctorId, + @Param("departmentId") Long departmentId, + @Param("queryDate") String queryDate, + @Param("tenantId") Integer tenantId, + @Param("practitionerId") Long practitionerId, + @Param("plannedStatus") Integer plannedStatus, + @Param("inProgressStatus") Integer inProgressStatus, + @Param("dischargedStatus") Integer dischargedStatus, + @Param("cancelledStatus") Integer cancelledStatus, + @Param("admitterCode") String admitterCode); + + /** + * 分页查询今日门诊患者列表 + * + * @param page 分页参数 + * @param queryWrapper 查询条件 + * @return 分页结果 + */ + @Select("") + IPage getTodayOutpatientPatients( + Page page, + @Param("ew") QueryWrapper queryWrapper, + @Param("tenantId") Integer tenantId, + @Param("admitterCode") String admitterCode); + + /** + * 获取患者详情 + * + * @param queryWrapper 查询条件 + * @return 患者详情 + */ + @Select("") + TodayOutpatientPatientDto getPatientDetail( + @Param("ew") QueryWrapper queryWrapper, + @Param("tenantId") Integer tenantId, + @Param("admitterCode") String admitterCode); + + /** + * 批量更新患者状态 + * + * @param encounterIds 就诊记录ID列表 + * @param targetStatus 目标状态 + * @param doctorId 医生ID + * @param updateTime 更新时间 + * @return 更新记录数 + */ + @Select("") + int batchUpdatePatientStatus( + @Param("encounterIds") List encounterIds, + @Param("targetStatus") Integer targetStatus, + @Param("doctorId") Long doctorId, + @Param("updateTime") Date updateTime); +} \ No newline at end of file diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/reportmanage/dto/InpatientMedicalRecordHomePageCollectionDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/reportmanage/dto/InpatientMedicalRecordHomePageCollectionDto.java index 434015bb..00764e48 100644 --- a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/reportmanage/dto/InpatientMedicalRecordHomePageCollectionDto.java +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/reportmanage/dto/InpatientMedicalRecordHomePageCollectionDto.java @@ -1,8 +1,8 @@ package com.openhis.web.reportmanage.dto; -import lombok.Data; -import lombok.experimental.Accessors; +import lombok.Getter; +import lombok.Setter; import java.math.BigDecimal; import java.util.Date; @@ -13,8 +13,8 @@ import java.util.Date; * @author yuxj * @date 2025/8/25 */ -@Data -@Accessors(chain = true) +@Getter +@Setter public class InpatientMedicalRecordHomePageCollectionDto { // 组织机构代码 字符 30 必填 diff --git a/openhis-server-new/openhis-application/src/main/resources/application-dev.yml b/openhis-server-new/openhis-application/src/main/resources/application-dev.yml index 500e9758..fe94317c 100644 --- a/openhis-server-new/openhis-application/src/main/resources/application-dev.yml +++ b/openhis-server-new/openhis-application/src/main/resources/application-dev.yml @@ -6,7 +6,7 @@ spring: druid: # 主库数据源 master: - url: jdbc:postgresql://47.116.196.11:15432/postgresql?currentSchema=hisdev&characterEncoding=UTF-8&client_encoding=UTF-8 + url: jdbc:postgresql://192.168.110.252:15432/postgresql?currentSchema=hisdev&characterEncoding=UTF-8&client_encoding=UTF-8 username: postgresql password: Jchl1528 # 从库数据源 @@ -64,9 +64,9 @@ spring: # redis 配置 redis: # 地址 - host: 47.116.196.11 + host: 192.168.110.252 # 端口,默认为6379 - port: 26379 + port: 6379 # 数据库索引 database: 1 # 密码 diff --git a/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml b/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml index 8ebf2ca6..5bc57ff6 100644 --- a/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml +++ b/openhis-server-new/openhis-application/src/main/resources/mapper/clinicalmanage/SurgeryMapper.xml @@ -13,6 +13,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + @@ -43,6 +47,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + @@ -68,14 +74,39 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" EXTRACT(YEAR FROM AGE(p.birth_date)) as patient_age, s.encounter_id, e.bus_no as encounter_no, + s.apply_doctor_id, + s.apply_doctor_name, + s.apply_dept_id, + s.apply_dept_name, s.surgery_name, s.surgery_code, s.surgery_type_enum, - s.surgery_type_enum as surgery_type_enum_dictText, + CASE s.surgery_type_enum + WHEN 1 THEN '门诊手术' + WHEN 2 THEN '住院手术' + WHEN 3 THEN '急诊手术' + WHEN 4 THEN '择期手术' + ELSE '未知' + END as surgery_type_enum_dictText, s.surgery_level, - s.surgery_level as surgery_level_dictText, + CASE s.surgery_level + WHEN 1 THEN '一级手术' + WHEN 2 THEN '二级手术' + WHEN 3 THEN '三级手术' + WHEN 4 THEN '四级手术' + WHEN 5 THEN '特级手术' + ELSE '未知' + END as surgery_level_dictText, s.status_enum, - s.status_enum as status_enum_dictText, + CASE s.status_enum + WHEN 0 THEN '待排期' + WHEN 1 THEN '已排期' + WHEN 2 THEN '手术中' + WHEN 3 THEN '已完成' + WHEN 4 THEN '已取消' + WHEN 5 THEN '暂停' + ELSE '未知' + END as status_enum_dictText, s.planned_time, s.actual_start_time, s.actual_end_time, @@ -90,14 +121,36 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" s.scrub_nurse_id, s.scrub_nurse_name, s.anesthesia_type_enum, - s.anesthesia_type_enum as anesthesia_type_enum_dictText, + CASE s.anesthesia_type_enum + WHEN 0 THEN '无麻醉' + WHEN 1 THEN '局部麻醉' + WHEN 2 THEN '区域麻醉' + WHEN 3 THEN '全身麻醉' + WHEN 4 THEN '脊椎麻醉' + WHEN 5 THEN '硬膜外麻醉' + WHEN 6 THEN '表面麻醉' + ELSE '未知' + END as anesthesia_type_enum_dictText, s.body_site, s.incision_level, - s.incision_level as incision_level_dictText, + CASE s.incision_level + WHEN 1 THEN 'I级切口' + WHEN 2 THEN 'II级切口' + WHEN 3 THEN 'III级切口' + WHEN 4 THEN 'IV级切口' + ELSE '未知' + END as incision_level_dictText, s.healing_level, - s.healing_level as healing_level_dictText, + CASE s.healing_level + WHEN 1 THEN '甲级愈合' + WHEN 2 THEN '乙级愈合' + WHEN 3 THEN '丙级愈合' + ELSE '未知' + END as healing_level_dictText, s.operating_room_id, s.operating_room_name, + r.organization_id as operating_room_org_id, + ro.name as operating_room_org_name, s.org_id, o.name as org_name, s.preoperative_diagnosis, @@ -114,6 +167,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" FROM cli_surgery s LEFT JOIN adm_patient p ON s.patient_id = p.id LEFT JOIN adm_encounter e ON s.encounter_id = e.id + LEFT JOIN adm_operating_room r ON s.operating_room_id = r.id + LEFT JOIN adm_organization ro ON r.organization_id = ro.id LEFT JOIN adm_organization o ON s.org_id = o.id @@ -122,7 +177,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" s.delete_flag = '0' - AND ${ew.sqlSegment} + AND ${ew.sqlSegment.replace('tenant_id', 's.tenant_id').replace('create_time', 's.create_time').replace('surgery_no', 's.surgery_no').replace('surgery_name', 's.surgery_name').replace('patient_name', 'p.name').replace('main_surgeon_name', 's.main_surgeon_name').replace('anesthetist_name', 's.anesthetist_name').replace('org_name', 'o.name')} @@ -132,4 +187,4 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" WHERE s.id = #{id} AND s.delete_flag = '0' - + \ No newline at end of file diff --git a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/AssignSeqEnum.java b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/AssignSeqEnum.java index 127e552a..5f6c58dd 100644 --- a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/AssignSeqEnum.java +++ b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/enums/AssignSeqEnum.java @@ -297,7 +297,12 @@ public enum AssignSeqEnum { /** * 自动备份单据号 */ - AUTO_BACKUP_NO("70", "自动备份单据号", "ABU"); + AUTO_BACKUP_NO("70", "自动备份单据号", "ABU"), + + /** + * 手术室业务编码 + */ + OPERATING_ROOM_BUS_NO("71", "手术室业务编码", "OPR"); private final String code; private final String info; diff --git a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/utils/HisQueryUtils.java b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/utils/HisQueryUtils.java index f794bf28..9c378623 100644 --- a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/utils/HisQueryUtils.java +++ b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/utils/HisQueryUtils.java @@ -81,21 +81,29 @@ public class HisQueryUtils { if (entity == null) { return queryWrapper; } - // 反射获取实体类的字段 - Field[] fields = entity.getClass().getDeclaredFields(); - for (Field field : fields) { - field.setAccessible(true); - try { - Object value = field.get(entity); - if (value != null && !value.toString().equals("")) { - // 将驼峰命名的字段名转换为下划线命名的数据库字段名 - String fieldName = camelToUnderline(field.getName()); - // 处理等于条件 - queryWrapper.eq(fieldName, value); + // 反射获取实体类的所有字段(包括父类) + Class currentClass = entity.getClass(); + while (currentClass != null && currentClass != Object.class) { + Field[] fields = currentClass.getDeclaredFields(); + for (Field field : fields) { + // 跳过静态字段,如 serialVersionUID + if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { + continue; + } + field.setAccessible(true); + try { + Object value = field.get(entity); + if (value != null && !value.toString().equals("")) { + // 将驼峰命名的字段名转换为下划线命名的数据库字段名 + String fieldName = camelToUnderline(field.getName()); + // 处理等于条件 + queryWrapper.eq(fieldName, value); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); } - } catch (IllegalAccessException e) { - e.printStackTrace(); } + currentClass = currentClass.getSuperclass(); } return queryWrapper; } diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/domain/OperatingRoom.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/domain/OperatingRoom.java new file mode 100644 index 00000000..0be7c6ec --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/domain/OperatingRoom.java @@ -0,0 +1,61 @@ +package com.openhis.administration.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.core.common.core.domain.HisBaseEntity; +import com.openhis.common.enums.LocationStatus; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 手术室管理Entity实体 + * + * @author system + * @date 2026-01-04 + */ +@Data +@TableName("adm_operating_room") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +public class OperatingRoom extends HisBaseEntity { + + /** ID */ + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + /** 编码 */ + private String busNo; + + /** 手术室名称 */ + private String name; + + /** 所属机构ID */ + private Long organizationId; + + /** 位置描述 */ + private String locationDescription; + + /** 设备配置 */ + private String equipmentConfig; + + /** 容纳人数 */ + private Integer capacity; + + /** 状态编码(1-启用,0-停用) */ + private Integer statusEnum; + + /** 显示顺序 */ + private Integer displayOrder; + + /** 拼音码 */ + private String pyStr; + + /** 五笔码 */ + private String wbStr; + + public OperatingRoom() { + this.statusEnum = LocationStatus.ACTIVE.getValue(); + } +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/mapper/OperatingRoomMapper.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/mapper/OperatingRoomMapper.java new file mode 100644 index 00000000..6cbc0de4 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/mapper/OperatingRoomMapper.java @@ -0,0 +1,15 @@ +package com.openhis.administration.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.openhis.administration.domain.OperatingRoom; +import org.apache.ibatis.annotations.Mapper; + +/** + * 手术室Mapper接口 + * + * @author system + * @date 2026-01-04 + */ +@Mapper +public interface OperatingRoomMapper extends BaseMapper { +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOperatingRoomService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOperatingRoomService.java new file mode 100644 index 00000000..fe33b6da --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOperatingRoomService.java @@ -0,0 +1,13 @@ +package com.openhis.administration.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.openhis.administration.domain.OperatingRoom; + +/** + * 手术室Service接口 + * + * @author system + * @date 2026-01-04 + */ +public interface IOperatingRoomService extends IService { +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OperatingRoomServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OperatingRoomServiceImpl.java new file mode 100644 index 00000000..b0f8d425 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OperatingRoomServiceImpl.java @@ -0,0 +1,18 @@ +package com.openhis.administration.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.openhis.administration.domain.OperatingRoom; +import com.openhis.administration.mapper.OperatingRoomMapper; +import com.openhis.administration.service.IOperatingRoomService; +import org.springframework.stereotype.Service; + +/** + * 手术室Service实现类 + * + * @author system + * @date 2026-01-04 + */ +@Service +public class OperatingRoomServiceImpl extends ServiceImpl + implements IOperatingRoomService { +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Surgery.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Surgery.java index 7d81e6b5..327c713f 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Surgery.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Surgery.java @@ -38,10 +38,35 @@ public class Surgery extends HisBaseEntity { @JsonSerialize(using = ToStringSerializer.class) private Long patientId; + /** 患者姓名 */ + @TableField("patient_name") + private String patientName; + /** 就诊ID */ @JsonSerialize(using = ToStringSerializer.class) private Long encounterId; + /** 申请医生ID */ + @JsonSerialize(using = ToStringSerializer.class) + @TableField("apply_doctor_id") + private Long applyDoctorId; + + /** 申请医生姓名 */ + @TableField("apply_doctor_name") + private String applyDoctorName; + + /** 申请科室ID */ + @JsonSerialize(using = ToStringSerializer.class) + @TableField("apply_dept_id") + private Long applyDeptId; + + /** 申请科室名称 */ + @TableField("apply_dept_name") + private String applyDeptName; + + /** 手术指征 */ + private String surgeryIndication; + /** 手术名称 */ private String surgeryName; @@ -49,112 +74,141 @@ public class Surgery extends HisBaseEntity { private String surgeryCode; /** 手术类型编码 */ + @TableField("surgery_type_enum") private Integer surgeryTypeEnum; /** 手术等级 */ + @TableField("surgery_level") private Integer surgeryLevel; /** 手术状态 */ + @TableField("status_enum") private Integer statusEnum; /** 计划手术时间 */ + @TableField("planned_time") private Date plannedTime; /** 实际开始时间 */ + @TableField("actual_start_time") private Date actualStartTime; /** 实际结束时间 */ + @TableField("actual_end_time") private Date actualEndTime; /** 主刀医生ID */ @JsonSerialize(using = ToStringSerializer.class) + @TableField("main_surgeon_id") private Long mainSurgeonId; /** 主刀医生姓名 */ + @TableField("main_surgeon_name") private String mainSurgeonName; /** 助手1 ID */ @JsonSerialize(using = ToStringSerializer.class) + @TableField("assistant_1_id") private Long assistant1Id; /** 助手1 姓名 */ + @TableField("assistant_1_name") private String assistant1Name; /** 助手2 ID */ @JsonSerialize(using = ToStringSerializer.class) + @TableField("assistant_2_id") private Long assistant2Id; /** 助手2 姓名 */ + @TableField("assistant_2_name") private String assistant2Name; /** 麻醉医生ID */ @JsonSerialize(using = ToStringSerializer.class) + @TableField("anesthetist_id") private Long anesthetistId; /** 麻醉医生姓名 */ + @TableField("anesthetist_name") private String anesthetistName; /** 巡回护士ID */ @JsonSerialize(using = ToStringSerializer.class) + @TableField("scrub_nurse_id") private Long scrubNurseId; /** 巡回护士姓名 */ + @TableField("scrub_nurse_name") private String scrubNurseName; /** 麻醉方式编码 */ + @TableField("anesthesia_type_enum") private Integer anesthesiaTypeEnum; /** 手术部位 */ + @TableField("body_site") private String bodySite; /** 手术切口等级 */ + @TableField("incision_level") private Integer incisionLevel; /** 手术切口愈合等级 */ + @TableField("healing_level") private Integer healingLevel; /** 手术室 */ @JsonSerialize(using = ToStringSerializer.class) + @TableField("operating_room_id") private Long operatingRoomId; /** 手术室名称 */ + @TableField("operating_room_name") private String operatingRoomName; /** 执行科室ID */ @JsonSerialize(using = ToStringSerializer.class) + @TableField("org_id") private Long orgId; /** 执行科室名称 */ + @TableField("org_name") private String orgName; /** 术前诊断 */ + @TableField("preoperative_diagnosis") private String preoperativeDiagnosis; /** 术后诊断 */ + @TableField("postoperative_diagnosis") private String postoperativeDiagnosis; /** 手术经过描述 */ + @TableField("surgery_description") private String surgeryDescription; /** 术后医嘱 */ + @TableField("postoperative_advice") private String postoperativeAdvice; /** 并发症描述 */ + @TableField("complications") private String complications; /** 手术费用 */ + @TableField("surgery_fee") private BigDecimal surgeryFee; /** 麻醉费用 */ + @TableField("anesthesia_fee") private BigDecimal anesthesiaFee; /** 总费用 */ + @TableField("total_fee") private BigDecimal totalFee; /** 备注信息 */ + @TableField("remark") private String remark; - - /** 租户ID(表不存在此字段,仅用于继承基类) */ - @TableField(exist = false) - private Integer tenantId; -} +} \ No newline at end of file diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/SurgeryServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/SurgeryServiceImpl.java index ad444590..e34c3d78 100644 --- a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/SurgeryServiceImpl.java +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/SurgeryServiceImpl.java @@ -2,32 +2,26 @@ package com.openhis.clinical.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.core.common.utils.AssignSeqUtil; import com.openhis.clinical.domain.Surgery; import com.openhis.clinical.mapper.SurgeryMapper; import com.openhis.clinical.service.ISurgeryService; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; +import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Random; -/** - * 手术管理Service业务层处理 - * - * @author system - * @date 2025-12-30 - */ +@Slf4j @Service public class SurgeryServiceImpl extends ServiceImpl implements ISurgeryService { @Resource private SurgeryMapper surgeryMapper; - @Resource - private AssignSeqUtil assignSeqUtil; - /** * 新增手术信息 * @@ -37,22 +31,53 @@ public class SurgeryServiceImpl extends ServiceImpl impl @Override @Transactional(rollbackFor = Exception.class) public Long insertSurgery(Surgery surgery) { - // 生成手术编号 - String surgeryNo = assignSeqUtil.getSeq("SS", 10); + // 生成手术单号:OP+年月日+4位随机数 + String surgeryNo = generateSurgeryNo(); surgery.setSurgeryNo(surgeryNo); surgery.setCreateTime(new Date()); surgery.setUpdateTime(new Date()); surgery.setDeleteFlag("0"); - // 默认状态为待排期 + // 默认状态为待排期(新开) if (surgery.getStatusEnum() == null) { surgery.setStatusEnum(0); } + // 添加日志,检查字段的值 + log.info("准备插入手术记录 - applyDoctorId: {}, applyDoctorName: {}, applyDeptId: {}, applyDeptName: {}", + surgery.getApplyDoctorId(), surgery.getApplyDoctorName(), + surgery.getApplyDeptId(), surgery.getApplyDeptName()); + surgeryMapper.insert(surgery); + + // 插入后再查询一次,验证是否保存成功 + Surgery inserted = surgeryMapper.selectById(surgery.getId()); + log.info("插入后查询结果 - applyDoctorId: {}, applyDoctorName: {}, applyDeptId: {}, applyDeptName: {}", + inserted.getApplyDoctorId(), inserted.getApplyDoctorName(), + inserted.getApplyDeptId(), inserted.getApplyDeptName()); + return surgery.getId(); } + /** + * 生成手术单号 + * 格式:OP+年月日+4位随机数 + * 示例:OP2025092003 + * + * @return 手术单号 + */ + private String generateSurgeryNo() { + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + String dateStr = sdf.format(new Date()); + + // 生成4位随机数 + Random random = new Random(); + int randomNum = random.nextInt(10000); + String randomStr = String.format("%04d", randomNum); + + return "OP" + dateStr + randomStr; + } + /** * 修改手术信息 * @@ -142,4 +167,4 @@ public class SurgeryServiceImpl extends ServiceImpl impl return surgeryMapper.updateById(surgery) > 0; } -} +} \ No newline at end of file diff --git a/openhis-server-new/pom.xml b/openhis-server-new/pom.xml index d5e48b8c..bd4dc322 100644 --- a/openhis-server-new/pom.xml +++ b/openhis-server-new/pom.xml @@ -348,12 +348,6 @@ ${jsqlparser.version} - - com.github.jsqlparser - jsqlparser - ${jsqlparser.version} - - diff --git a/openhis-ui-vue3/favicon/site.webmanifest b/openhis-ui-vue3/favicon/site.webmanifest index 68994ad4..e698b5ff 100644 --- a/openhis-ui-vue3/favicon/site.webmanifest +++ b/openhis-ui-vue3/favicon/site.webmanifest @@ -1,19 +1,20 @@ { - "name": "My Awesome App", - "short_name": "AwesomeApp", + "name": "医院信息管理系统", + "short_name": "HIS", "icons": [ { - "src": "/android-chrome-192x192.png", + "src": "/favicon/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { - "src": "/android-chrome-512x512.png", + "src": "/favicon/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } ], - "theme_color": "#ffffff", + "theme_color": "#1890ff", "background_color": "#ffffff", - "display": "standalone" + "display": "standalone", + "description": "医院信息管理系统 - 提供全面的医疗信息化解决方案" } \ No newline at end of file diff --git a/openhis-ui-vue3/index.html b/openhis-ui-vue3/index.html index 003a4ea3..639db44a 100644 --- a/openhis-ui-vue3/index.html +++ b/openhis-ui-vue3/index.html @@ -13,7 +13,7 @@ - + @@ -27,7 +27,7 @@ - + diff --git a/openhis-ui-vue3/src/api/operatingroom.js b/openhis-ui-vue3/src/api/operatingroom.js new file mode 100644 index 00000000..9d979bd1 --- /dev/null +++ b/openhis-ui-vue3/src/api/operatingroom.js @@ -0,0 +1,90 @@ +import request from '@/utils/request' + +/** + * 查询手术室列表 + * @param {Object} query - 查询参数 + * @returns {Promise} 请求结果 + */ +export function listOperatingRoom(query) { + return request({ + url: '/base-data-manage/operating-room/list', + method: 'get', + params: query + }) +} + +/** + * 查询手术室详细 + * @param {Long} id - 手术室ID + * @returns {Promise} 请求结果 + */ +export function getOperatingRoom(id) { + return request({ + url: '/base-data-manage/operating-room/' + id, + method: 'get' + }) +} + +/** + * 新增手术室 + * @param {Object} data - 手术室信息 + * @returns {Promise} 请求结果 + */ +export function addOperatingRoom(data) { + return request({ + url: '/base-data-manage/operating-room', + method: 'post', + data: data + }) +} + +/** + * 修改手术室 + * @param {Object} data - 手术室信息 + * @returns {Promise} 请求结果 + */ +export function updateOperatingRoom(data) { + return request({ + url: '/base-data-manage/operating-room', + method: 'put', + data: data + }) +} + +/** + * 删除手术室 + * @param {Long|Array} ids - 手术室ID或ID数组 + * @returns {Promise} 请求结果 + */ +export function deleteOperatingRoom(ids) { + return request({ + url: '/base-data-manage/operating-room/' + ids, + method: 'delete' + }) +} + +/** + * 启用手术室 + * @param {Array} ids - 手术室ID数组 + * @returns {Promise} 请求结果 + */ +export function enableOperatingRoom(ids) { + return request({ + url: '/base-data-manage/operating-room/enable', + method: 'put', + data: ids + }) +} + +/** + * 停用手术室 + * @param {Array} ids - 手术室ID数组 + * @returns {Promise} 请求结果 + */ +export function disableOperatingRoom(ids) { + return request({ + url: '/base-data-manage/operating-room/disable', + method: 'put', + data: ids + }) +} diff --git a/openhis-ui-vue3/src/api/surgerymanage.js b/openhis-ui-vue3/src/api/surgerymanage.js index 9fff188c..b29e9d76 100644 --- a/openhis-ui-vue3/src/api/surgerymanage.js +++ b/openhis-ui-vue3/src/api/surgerymanage.js @@ -78,3 +78,16 @@ export function updateSurgeryStatus(id, statusEnum) { params: { id, statusEnum } }) } + +/** + * 根据患者ID查询就诊列表 + * @param patientId 患者ID + * @returns {AxiosPromise} + */ +export function getEncounterListByPatientId(patientId) { + return request({ + url: '/clinical-manage/surgery/encounter-list', + method: 'get', + params: { patientId } + }) +} diff --git a/openhis-ui-vue3/src/assets/icons/svg/patient.svg b/openhis-ui-vue3/src/assets/icons/svg/patient.svg index 283b9c42..18d010ae 100644 --- a/openhis-ui-vue3/src/assets/icons/svg/patient.svg +++ b/openhis-ui-vue3/src/assets/icons/svg/patient.svg @@ -1,4 +1,4 @@ - + diff --git a/openhis-ui-vue3/src/assets/icons/svg/redis-list.svg b/openhis-ui-vue3/src/assets/icons/svg/redis-list.svg index 710cdf3b..0c257379 100644 --- a/openhis-ui-vue3/src/assets/icons/svg/redis-list.svg +++ b/openhis-ui-vue3/src/assets/icons/svg/redis-list.svg @@ -1,4 +1,4 @@ \ No newline at end of file diff --git a/openhis-ui-vue3/src/router/index.js b/openhis-ui-vue3/src/router/index.js index c04ab127..fbd2a60b 100644 --- a/openhis-ui-vue3/src/router/index.js +++ b/openhis-ui-vue3/src/router/index.js @@ -91,28 +91,7 @@ export const constantRoutes = [ { path: '/tpr', component: () => import('@/views/inpatientNurse/tprsheet/index.vue'), - }, - // { - // path: '/patientmanagement', - // component: Layout, - // redirect: '/patientmanagement/patientmanagement', - // name: 'PatientManagement', - // meta: { title: '患者管理', icon: 'patient' }, - // children: [ - // { - // path: 'patientmanagement', - // component: () => import('@/views/patientmanagement/patientmanagement/index.vue'), - // name: 'PatientManagementList', - // meta: { title: '患者档案管理', icon: 'patient' }, - // }, - // { - // path: 'outpatienrecords', - // component: () => import('@/views/patientmanagement/outpatienrecords/index.vue'), - // name: 'OutpatientRecords', - // meta: { title: '门诊就诊记录', icon: 'record' }, - // }, - // ], - // }, + } ]; // 动态路由 - 基于用户权限动态加载的路由 @@ -192,58 +171,19 @@ export const dynamicRoutes = [ // meta: { title: '系统管理', icon: 'system' }, // children: [ // { - // path: 'user', // 用户管理路由 - // component: () => import('@/views/system/user/index.vue'), - // name: 'User', - // meta: { title: '用户管理', icon: 'user', permissions: ['system:user:list'] } - // }, - // { - // path: 'role', // 角色管理路由 - // component: () => import('@/views/system/role/index.vue'), - // name: 'Role', - // meta: { title: '角色管理', icon: 'role', permissions: ['system:role:list'] } - // }, - // { - // path: 'menu', // 菜单管理路由 - // component: () => import('@/views/system/menu/index.vue'), - // name: 'Menu', - // meta: { title: '菜单管理', icon: 'menu', permissions: ['system:menu:list'] } - // }, - // { - // path: 'dept', // 部门管理路由 - // component: () => import('@/views/system/dept/index.vue'), - // name: 'Dept', - // meta: { title: '部门管理', icon: 'dept', permissions: ['system:dept:list'] } - // }, - // { - // path: 'post', // 岗位管理路由 - // component: () => import('@/views/system/post/index.vue'), - // name: 'Post', - // meta: { title: '岗位管理', icon: 'post', permissions: ['system:post:list'] } - // }, - // { - // path: 'dict', // 字典管理路由 - // component: () => import('@/views/system/dict/index.vue'), - // name: 'Dict', - // meta: { title: '字典管理', icon: 'dict', permissions: ['system:dict:list'] } - // }, - // { - // path: 'config', // 参数配置路由 - // component: () => import('@/views/system/config/index.vue'), - // name: 'Config', - // meta: { title: '参数配置', icon: 'config', permissions: ['system:config:list'] } - // }, - // { - // path: 'notice', // 通知公告路由 - // component: () => import('@/views/system/notice/index.vue'), - // name: 'Notice', - // meta: { title: '通知公告', icon: 'notice', permissions: ['system:notice:list'] } - // }, - // { - // path: 'tenant', // 租户管理路由 - // component: () => import('@/views/system/tenant/index.vue'), - // name: 'Tenant', - // meta: { title: '租户管理', icon: 'tenant', permissions: ['system:tenant:list'] } + // path: 'basicdata', + // component: Layout, + // redirect: '/system/basicdata/location', + // name: 'BasicData', + // meta: { title: '基础数据', icon: 'location' }, + // children: [ + // { + // path: 'operatingroom', + // component: () => import('@/views/operatingroom/index.vue'), + // name: 'OperatingRoomManage', + // meta: { title: '手术室管理' } + // } + // ] // } // ] // }, diff --git a/openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue b/openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue new file mode 100644 index 00000000..eb72ffca --- /dev/null +++ b/openhis-ui-vue3/src/views/doctorstation/components/surgery/surgeryApplication.vue @@ -0,0 +1,715 @@ + + + + + + diff --git a/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue new file mode 100644 index 00000000..e562e9dc --- /dev/null +++ b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue @@ -0,0 +1,633 @@ + + + + + \ No newline at end of file diff --git a/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientStats.vue b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientStats.vue new file mode 100644 index 00000000..d74cad86 --- /dev/null +++ b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientStats.vue @@ -0,0 +1,303 @@ + + + + + \ No newline at end of file diff --git a/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/api.js b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/api.js new file mode 100644 index 00000000..095f450d --- /dev/null +++ b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/api.js @@ -0,0 +1,95 @@ +import request from '@/utils/request' + +// 获取今日门诊统计信息 +export function getTodayOutpatientStats() { + return request({ + url: '/today-outpatient/stats', + method: 'get' + }) +} + +// 分页查询今日门诊患者列表 +export function getTodayOutpatientPatients(queryParams) { + return request({ + url: '/today-outpatient/patients', + method: 'get', + params: queryParams + }) +} + +// 获取今日待就诊患者队列 +export function getWaitingPatients() { + return request({ + url: '/today-outpatient/patients/waiting', + method: 'get' + }) +} + +// 获取今日就诊中患者列表 +export function getInProgressPatients() { + return request({ + url: '/today-outpatient/patients/in-progress', + method: 'get' + }) +} + +// 获取今日已完成就诊患者列表 +export function getCompletedPatients() { + return request({ + url: '/today-outpatient/patients/completed', + method: 'get' + }) +} + +// 获取患者就诊详情 +export function getPatientDetail(encounterId) { + return request({ + url: `/today-outpatient/patients/${encounterId}`, + method: 'get' + }) +} + +// 批量更新患者状态 +export function batchUpdatePatientStatus(encounterIds, targetStatus) { + return request({ + url: '/today-outpatient/patients/batch-update-status', + method: 'post', + params: { + encounterIds: encounterIds.join(','), + targetStatus + } + }) +} + +// 接诊患者 +export function receivePatient(encounterId) { + return request({ + url: `/today-outpatient/patients/${encounterId}/receive`, + method: 'post' + }) +} + +// 完成就诊 +export function completeVisit(encounterId) { + return request({ + url: `/today-outpatient/patients/${encounterId}/complete`, + method: 'post' + }) +} + +// 取消就诊 +export function cancelVisit(encounterId, reason) { + return request({ + url: `/today-outpatient/patients/${encounterId}/cancel`, + method: 'post', + params: { reason } + }) +} + +// 快速接诊 +export function quickReceivePatient(encounterId) { + return request({ + url: `/today-outpatient/quick-receive/${encounterId}`, + method: 'post' + }) +} \ No newline at end of file diff --git a/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/index.vue b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/index.vue new file mode 100644 index 00000000..16c0adf9 --- /dev/null +++ b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/index.vue @@ -0,0 +1,753 @@ + + + + + \ No newline at end of file diff --git a/openhis-ui-vue3/src/views/doctorstation/index.vue b/openhis-ui-vue3/src/views/doctorstation/index.vue index db3cfcd3..291372c2 100644 --- a/openhis-ui-vue3/src/views/doctorstation/index.vue +++ b/openhis-ui-vue3/src/views/doctorstation/index.vue @@ -164,6 +164,9 @@ + + + @@ -217,6 +220,7 @@ import eprescriptionlist from './components/eprescriptionlist.vue'; import HospitalizationDialog from './components/hospitalizationDialog.vue'; import tcmAdvice from './components/tcm/tcmAdvice.vue'; import inspectionApplication from './components/inspection/inspectionApplication.vue'; +import surgeryApplication from './components/surgery/surgeryApplication.vue'; import {formatDate, formatDateStr} from '@/utils/index'; import useUserStore from '@/store/modules/user'; import {nextTick} from 'vue'; @@ -266,6 +270,7 @@ const patientDrawerRef = ref(); const prescriptionRef = ref(); const tcmRef = ref(); const inspectionRef = ref(); +const surgeryRef = ref(); const emrRef = ref(); const diagnosisRef = ref(); const waitCount = ref(0); @@ -402,6 +407,9 @@ function handleClick(tab) { case 'inspection': // 检验tab点击处理逻辑可以在这里添加 break; + case 'surgery': + surgeryRef.value.getList(); + break; case 'eprescription': eprescriptionRef.value.getList(); break; @@ -460,6 +468,7 @@ function handleCardClick(item, index) { prescriptionRef.value.getListInfo(); tcmRef.value.getListInfo(); inspectionRef.value.getList(); + surgeryRef.value.getList(); diagnosisRef.value.getList(); eprescriptionRef.value.getList(); // emrRef.value.getDetail(item.encounterId); diff --git a/openhis-ui-vue3/src/views/doctorstation/todayOutpatient.vue b/openhis-ui-vue3/src/views/doctorstation/todayOutpatient.vue new file mode 100644 index 00000000..ed07a2de --- /dev/null +++ b/openhis-ui-vue3/src/views/doctorstation/todayOutpatient.vue @@ -0,0 +1,372 @@ + + + + + \ No newline at end of file diff --git a/openhis-ui-vue3/src/views/index.vue b/openhis-ui-vue3/src/views/index.vue index a530ae4e..ebf4f8b5 100644 --- a/openhis-ui-vue3/src/views/index.vue +++ b/openhis-ui-vue3/src/views/index.vue @@ -409,9 +409,12 @@ const handleStatClick = (stat) => { } else if (stat.key === 'todayRevenue' || stat.key === 'todayPayments') { // 跳转到收费页面 router.push('/charge/cliniccharge') - } else if (stat.key === 'appointments' || stat.key === 'todayAppointments') { + } else if (stat.key === 'appointments') { // 跳转到预约管理页面 router.push('/appoinmentmanage') + } else if (stat.key === 'todayAppointments') { + // 跳转到今日门诊模块 + router.push('/doctorstation/today-outpatient') } else if (stat.key === 'pendingApprovals' || stat.key === 'pendingReview') { // 跳转到待审核页面 router.push('/clinicmanagement/ePrescribing') diff --git a/openhis-ui-vue3/src/views/operatingroom/index.vue b/openhis-ui-vue3/src/views/operatingroom/index.vue new file mode 100644 index 00000000..6b7e5937 --- /dev/null +++ b/openhis-ui-vue3/src/views/operatingroom/index.vue @@ -0,0 +1,501 @@ + + + + + diff --git a/openhis-ui-vue3/src/views/patientmanagement/outpatienrecords/index.vue b/openhis-ui-vue3/src/views/patientmanagement/outpatienrecords/index.vue index bd24ee28..5e62e893 100644 --- a/openhis-ui-vue3/src/views/patientmanagement/outpatienrecords/index.vue +++ b/openhis-ui-vue3/src/views/patientmanagement/outpatienrecords/index.vue @@ -49,10 +49,11 @@ clearable style="width: 120px" > - - - - + + + + + @@ -181,16 +182,18 @@ function getList() { /** 根据状态获取标签类型 */ function getStatusTagType(status) { - // 假设状态值:1-待就诊,2-就诊中,3-已完成,4-已取消 + // 状态值对应后端 EncounterSubjectStatus 枚举:1-已到达,2-已分诊,3-已看诊,4-已离开,5-已完成 switch (status) { case 1: - return 'warning'; // 待就诊 - 黄色 + return 'warning'; // 已到达 - 黄色 case 2: - return 'primary'; // 就诊中 - 蓝色 + return 'primary'; // 已分诊 - 蓝色 case 3: - return 'success'; // 已完成 - 绿色 + return 'success'; // 已看诊 - 绿色 case 4: - return 'info'; // 已取消 - 灰色 + return 'info'; // 已离开 - 灰色 + case 5: + return 'success'; // 已完成 - 绿色 default: return ''; } diff --git a/openhis-ui-vue3/src/views/surgerymanage/index.vue b/openhis-ui-vue3/src/views/surgerymanage/index.vue index 0778d025..f12baccb 100644 --- a/openhis-ui-vue3/src/views/surgerymanage/index.vue +++ b/openhis-ui-vue3/src/views/surgerymanage/index.vue @@ -78,32 +78,63 @@ - + - + - + - + - + - + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + @@ -139,6 +179,11 @@ + + + + + @@ -147,23 +192,52 @@ - + +
* 编辑模式下患者信息不可更改
- - - + + + + +
+ 原就诊记录: {{ form.encounterNo || '无' }} +
+
+
+
+ + + + + + + + + + @@ -171,12 +245,12 @@ - + - + @@ -184,7 +258,7 @@ - + - + - + @@ -232,24 +307,24 @@ - + - + @@ -259,24 +334,24 @@ - + - + @@ -286,19 +361,19 @@ - + - + - - - + + + @@ -329,6 +416,8 @@ placeholder="请选择执行科室" check-strictly style="width: 100%" + :disabled="isViewMode" + @change="handleOrgChange" /> @@ -337,35 +426,35 @@ 诊断信息 - + - + - + - + - + - + - + @@ -373,7 +462,7 @@ - + - + - + - +
- - - - {{ viewData.surgeryNo }} - - {{ viewData.statusEnum_dictText }} - - {{ viewData.patientName }} - {{ viewData.patientGender }} / {{ viewData.patientAge }}岁 - {{ viewData.encounterNo }} - {{ viewData.surgeryName }} - {{ viewData.surgeryCode }} - {{ viewData.surgeryTypeEnum_dictText }} - {{ viewData.surgeryLevel_dictText }} - {{ viewData.anesthesiaTypeEnum_dictText }} - {{ viewData.plannedTime }} - {{ viewData.actualStartTime }} - {{ viewData.actualEndTime }} - {{ viewData.bodySite }} - {{ viewData.mainSurgeonName }} - {{ viewData.anesthetistName }} - {{ viewData.assistant1Name }} - {{ viewData.assistant2Name }} - {{ viewData.operatingRoomName }} - {{ viewData.orgName }} - {{ viewData.preoperativeDiagnosis }} - {{ viewData.postoperativeDiagnosis }} - ¥{{ viewData.surgeryFee }} - ¥{{ viewData.anesthesiaFee }} - ¥{{ viewData.totalFee }} - {{ viewData.remark }} - -