From fb9f85e9676fa6314b979cb4099c36b194d867f7 Mon Sep 17 00:00:00 2001 From: chenqi Date: Thu, 8 Jan 2026 14:52:22 +0800 Subject: [PATCH 1/7] =?UTF-8?q?chore(router):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=82=A3=E8=80=85=E6=A1=A3=E6=A1=88=E7=AE=A1=E7=90=86=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加患者档案管理路由配置代码 - 注释掉租户用户设置路由部分代码 - 新增patientmgr路由项配置 - 配置路由组件和元信息 - 设置路由隐藏属性 - 完善路由路径和名称定义 --- openhis-ui-vue3/src/router/index.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/openhis-ui-vue3/src/router/index.js b/openhis-ui-vue3/src/router/index.js index 4bbfba04..806091ac 100644 --- a/openhis-ui-vue3/src/router/index.js +++ b/openhis-ui-vue3/src/router/index.js @@ -188,6 +188,19 @@ export const dynamicRoutes = [ // ] // }, // 租户用户设置路由 + //{ + // path: '/patient', + // component: Layout, + // hidden: true, + // children: [ + // { + // path: 'patientmgr', + // component: () => import('@/views/patientmanagement/patientmanagement/index.vue'), + // name: 'Patientmgr', + // meta: { title: '患者档案管理', icon: 'user' } + // } + // ] + // }, { path: '/system/tenant-user', component: Layout, From 062c4a92b8bab9a1526fd5818244c374a099746b Mon Sep 17 00:00:00 2001 From: chenqi Date: Thu, 8 Jan 2026 14:52:28 +0800 Subject: [PATCH 2/7] =?UTF-8?q?chore(router):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=82=A3=E8=80=85=E6=A1=A3=E6=A1=88=E7=AE=A1=E7=90=86=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加患者档案管理路由配置代码 - 注释掉租户用户设置路由部分代码 - 新增patientmgr路由项配置 - 配置路由组件和元信息 - 设置路由隐藏属性 - 完善路由路径和名称定义 --- .../TodayOutpatientPatientList.vue | 2 +- .../todayOutpatient/TodayOutpatientStats.vue | 2 +- .../components/intOperRecordSheet.vue | 2 +- .../inpatientNurse/components/patientList.vue | 2 +- openhis-ui-vue3/test-util-extend.js | 25 ------------------- 5 files changed, 4 insertions(+), 29 deletions(-) delete mode 100644 openhis-ui-vue3/test-util-extend.js diff --git a/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue index e562e9dc..d69bba5f 100644 --- a/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue +++ b/openhis-ui-vue3/src/views/doctorstation/components/todayOutpatient/TodayOutpatientPatientList.vue @@ -205,7 +205,7 @@ +.print-section { + margin-bottom: 20px; +} + +.section-title { + font-size: 14px; + font-weight: bold; + margin-bottom: 10px; + border-bottom: 1px solid #ddd; + padding-bottom: 5px; +} + +.info-row { + margin-bottom: 8px; + font-size: 13px; +} + +.info-row .label { + display: inline-block; + width: 100px; + font-weight: bold; +} + +.info-row .value { + display: inline-block; +} + +.fee-table { + width: 100%; + border-collapse: collapse; + margin-top: 10px; +} + +.fee-table th, +.fee-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; +} + +.fee-table th { + background-color: #f5f5f5; + font-weight: bold; +} + +.total-label { + font-weight: bold; + text-align: right; +} + +.total-value { + font-weight: bold; + color: red; +} + +.print-footer { + margin-top: 20px; + font-size: 12px; + color: #666; +} + +.reminder { + text-align: center; + padding: 10px; + background-color: #f9f9f9; + border-radius: 4px; +} + diff --git a/openhis-ui-vue3/src/views/charge/outpatientregistration/index.vue b/openhis-ui-vue3/src/views/charge/outpatientregistration/index.vue index 2001d9b4..0de63a26 100644 --- a/openhis-ui-vue3/src/views/charge/outpatientregistration/index.vue +++ b/openhis-ui-vue3/src/views/charge/outpatientregistration/index.vue @@ -4,9 +4,9 @@ @@ -617,6 +639,7 @@ import patientList from './components/patientList'; import {nextTick, onMounted, onUnmounted, ref} from 'vue'; import ChargeDialog from './components/chargeDialog.vue'; import RefundDialog from './components/refundDialog.vue'; +import ReprintDialog from './components/reprintDialog.vue'; import {handleColor} from '@/utils/his'; import useUserStore from '@/store/modules/user'; import {formatDateStr} from '@/utils/index'; @@ -709,7 +732,6 @@ const data = reactive({ contractNo: [{ required: true, message: '费用性质', trigger: 'blur' }], patientId: [{ required: true, message: '病人不能为空', trigger: 'blur' }], priorityEnum: [{ required: true, message: '优先级不能为空', trigger: 'blur' }], - serviceTypeId: [{ required: true, message: '挂号类型不能为空', trigger: 'blur' }], organizationId: [{ required: true, message: '优先级不能为空', trigger: 'blur' }], orgId: [{ required: true, message: '就诊科室不能为空', trigger: 'blur' }], practitionerId: [{ required: true, message: '医生不能为空', trigger: 'blur' }], @@ -1026,10 +1048,18 @@ function getList() { outpatientRegistrationList.value = res.data.records; total.value = res.data.total; - // 调试:查看返回的数据结构(仅退号记录查询时) - if (queryType.value === 'returned' && res.data.records && res.data.records.length > 0) { - console.log('退号记录数据结构:', res.data.records[0]); + // 调试:查看返回的数据结构,查找就诊卡号字段 + if (res.data.records && res.data.records.length > 0) { + console.log('当日已挂号数据结构:', res.data.records[0]); console.log('所有字段:', Object.keys(res.data.records[0])); + // 查找可能的就诊卡号字段 + const firstRecord = res.data.records[0]; + const possibleCardFields = ['identifierNo', 'cardNo', 'card', 'patientCardNo', 'identifier', 'medicalCardNo']; + possibleCardFields.forEach(field => { + if (firstRecord[field] !== undefined) { + console.log(`找到可能的就诊卡号字段 ${field}:`, firstRecord[field]); + } + }); } }); } diff --git a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue index 3faf153f..776e2f8e 100644 --- a/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue +++ b/openhis-ui-vue3/src/views/maintainSystem/checkprojectSettings/components/PackageSettings.vue @@ -1144,6 +1144,7 @@ async function handleSave() { remark: formData.remark || '', createDate: formData.createDate, items: detailData.value.map((item, index) => ({ + // 基本字段(与检查套餐 CheckPackageDetail 对应) itemCode: item.code || '', itemName: item.itemName || '', checkItemId: item.itemId || null, @@ -1157,7 +1158,13 @@ async function handleSave() { serviceCharge: parseFloat(item.serviceCharge) || 0, total: parseFloat(item.total) || 0, origin: item.origin || '', - orderNum: index + 1 + orderNum: index + 1, + // 兼容字段(部分日志/历史代码使用的命名:dosage/route/serviceFee/totalAmount) + // 后端当前不会用到这些别名字段,但保留便于排查和兼容 + dosage: item.dose || '', + route: item.method || '', + serviceFee: parseFloat(item.serviceCharge) || 0, + totalAmount: parseFloat(item.total) || 0 })) } From 8c74d4533259dad1e5dfbc4a0c0b065e4d57d52a Mon Sep 17 00:00:00 2001 From: ljj <35349321@qq.com> Date: Fri, 9 Jan 2026 11:33:03 +0800 Subject: [PATCH 5/7] =?UTF-8?q?76=20=E9=97=A8=E8=AF=8A=E9=A2=84=E7=BA=A6?= =?UTF-8?q?=E6=8C=82=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .trae/documents/plan_20251231_062502.md | 26 + .trae/documents/plan_20251231_063300.md | 30 + .trae/documents/修复号源列表显示问题.md | 32 + .../修复门诊预约界面专家号查询问题.md | 23 + .../修复门诊预约界面只显示1条数据的问题.md | 23 + CheckTicketStatus.java | 33 + create_clinical_ticket_table.sql | 67 + .../com/core/common/utils/SecurityUtils.java | 19 + .../framework/aspectj/TransactionAspect.java | 31 +- .../appservice/ITicketAppService.java | 62 + .../appservice/impl/TicketAppServiceImpl.java | 363 ++++ .../controller/TicketController.java | 101 + .../web/appointmentmanage/dto/TicketDto.java | 102 + .../openhis/common/aspectj/OperLogAspect.java | 2 +- .../openhis/common/enums/AssignSeqEnum.java | 10 +- .../com/openhis/clinical/domain/Order.java | 68 + .../com/openhis/clinical/domain/Ticket.java | 107 + .../openhis/clinical/mapper/OrderMapper.java | 35 + .../openhis/clinical/mapper/TicketMapper.java | 82 + .../clinical/service/IOrderService.java | 37 + .../clinical/service/ITicketService.java | 105 + .../service/impl/OrderServiceImpl.java | 164 ++ .../service/impl/TicketServiceImpl.java | 267 +++ .../resources/mapper/clinical/OrderMapper.xml | 270 +++ .../mapper/clinical/TicketMapper.xml | 245 +++ openhis-server-new/start.bat | 10 + openhis-server-new/start.sh | 13 + .../src/api/appoinmentmanage/ticket.js | 57 + .../src/components/TopNav/index.vue | 129 +- .../layout/components/Sidebar/SidebarItem.vue | 2 +- .../src/layout/components/Sidebar/index.vue | 4 +- openhis-ui-vue3/src/router/index.js | 434 ++-- openhis-ui-vue3/src/store/modules/user.js | 17 +- .../src/views/appoinmentmanage/index.vue | 1681 +++++++++++++++ .../outpatientAppointment/index.vue | 1845 +++++++++++++++++ .../views/appoinmentmanage/ticketManage.vue | 1638 +++++++++++++++ package-lock.json | 289 ++- package.json | 5 + .../202512301200add_table_order_main.sql | 115 + .../202512301200verify_order_main.sql | 51 + .../门诊预约测试数据使用指南.md | 202 ++ 迁移记录-DB变更记录/门诊预约测试数据插入.sql | 89 + 42 files changed, 8627 insertions(+), 258 deletions(-) create mode 100644 .trae/documents/plan_20251231_062502.md create mode 100644 .trae/documents/plan_20251231_063300.md create mode 100644 .trae/documents/修复号源列表显示问题.md create mode 100644 .trae/documents/修复门诊预约界面专家号查询问题.md create mode 100644 .trae/documents/修复门诊预约界面只显示1条数据的问题.md create mode 100644 CheckTicketStatus.java create mode 100644 create_clinical_ticket_table.sql create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/ITicketAppService.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/TicketAppServiceImpl.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/TicketController.java create mode 100644 openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/dto/TicketDto.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Order.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Ticket.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/TicketMapper.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/IOrderService.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/ITicketService.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/OrderServiceImpl.java create mode 100644 openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java create mode 100644 openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml create mode 100644 openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/TicketMapper.xml create mode 100644 openhis-server-new/start.bat create mode 100644 openhis-server-new/start.sh create mode 100644 openhis-ui-vue3/src/api/appoinmentmanage/ticket.js create mode 100644 openhis-ui-vue3/src/views/appoinmentmanage/index.vue create mode 100644 openhis-ui-vue3/src/views/appoinmentmanage/outpatientAppointment/index.vue create mode 100644 openhis-ui-vue3/src/views/appoinmentmanage/ticketManage.vue create mode 100644 package.json create mode 100644 迁移记录-DB变更记录/202512301200add_table_order_main.sql create mode 100644 迁移记录-DB变更记录/202512301200verify_order_main.sql create mode 100644 迁移记录-DB变更记录/门诊预约测试数据使用指南.md create mode 100644 迁移记录-DB变更记录/门诊预约测试数据插入.sql diff --git a/.trae/documents/plan_20251231_062502.md b/.trae/documents/plan_20251231_062502.md new file mode 100644 index 00000000..227560de --- /dev/null +++ b/.trae/documents/plan_20251231_062502.md @@ -0,0 +1,26 @@ +# 修复门诊预约界面专家号查询结果显示问题 + +## 问题分析 +1. 前端传递的参数正确:`type=expert`,后端正确转换为`ticketType=专家` +2. 实际查询返回了5条记录,但COUNT查询只返回了1条记录 +3. 这导致前端只显示了1条记录,而不是全部5条 +4. 原因:MyBatis-Plus自动生成的COUNT查询和实际查询使用了不同的条件,特别是逻辑删除条件 + +## 解决方案 +1. 修改TicketMapper.xml中的自定义COUNT查询,显式添加`delete_flag = '0'`条件 +2. 在selectTicketPage和selectTicketPage_mpCount查询中都添加逻辑删除条件 +3. 确保两个查询使用完全相同的WHERE条件 + +## 修复步骤 +1. 修改`selectTicketPage`查询,添加逻辑删除条件`and delete_flag = '0'` +2. 修改`selectTicketPage_mpCount`查询,添加逻辑删除条件`and delete_flag = '0'` +3. 确保两个查询的WHERE条件完全一致 +4. 测试修复后的功能,确保专家号能正确显示全部5条记录 + +## 代码修改点 +- 文件:`d:/work/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/TicketMapper.xml` +- 查询:`selectTicketPage` 和 `selectTicketPage_mpCount` +- 修改内容:添加逻辑删除条件`and delete_flag = '0'` + +## 预期效果 +修复后,COUNT查询和实际查询将使用完全相同的条件,包括逻辑删除条件,从而确保COUNT查询返回正确的总记录数,前端能显示所有5条专家号记录。 \ No newline at end of file diff --git a/.trae/documents/plan_20251231_063300.md b/.trae/documents/plan_20251231_063300.md new file mode 100644 index 00000000..775f8451 --- /dev/null +++ b/.trae/documents/plan_20251231_063300.md @@ -0,0 +1,30 @@ +# 修复门诊预约界面专家号查询COUNT结果不正确问题 + +## 问题分析 +1. 前端传递的参数正确:`type=expert`,后端正确转换为`ticketType=专家` +2. COUNT查询和实际查询的WHERE条件完全相同:`WHERE delete_flag = '0' AND ticket_type = '专家'` +3. 但COUNT查询只返回1条记录,而实际查询返回5条记录 +4. 原因:MyBatis-Plus的分页插件在处理自定义COUNT查询时,存在bug,导致COUNT查询结果不正确 + +## 解决方案 +修改`TicketAppServiceImpl.java`中的`listTicket`方法,不使用MyBatis-Plus的自动分页功能,而是手动实现分页查询: +1. 直接调用`ticketService.countTickets`方法获取总记录数 +2. 手动构建查询条件 +3. 确保COUNT查询和实际查询使用完全相同的条件 + +## 修复步骤 +1. 修改`TicketAppServiceImpl.java`中的`listTicket`方法 +2. 手动实现分页查询,包括: + - 构建查询条件 + - 调用`countTickets`获取总记录数 + - 调用`selectTicketList`获取分页数据 + - 手动组装分页结果 +3. 测试修复后的功能,确保专家号能正确显示全部5条记录 + +## 代码修改点 +- 文件:`d:/work/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/TicketAppServiceImpl.java` +- 方法:`listTicket` +- 修改内容:替换MyBatis-Plus的自动分页,改为手动分页实现 + +## 预期效果 +修复后,COUNT查询和实际查询将使用完全相同的条件,COUNT查询将返回正确的总记录数(5条),前端能显示所有5条专家号记录。 \ No newline at end of file diff --git a/.trae/documents/修复号源列表显示问题.md b/.trae/documents/修复号源列表显示问题.md new file mode 100644 index 00000000..78a1672b --- /dev/null +++ b/.trae/documents/修复号源列表显示问题.md @@ -0,0 +1,32 @@ +## 问题分析 +根据日志和代码分析,发现号源列表显示"没有更多数据了"的问题原因: + +1. **后端查询正常**:成功查询到5条符合条件的专家号源记录 +2. **数据转换失败**:在`convertToDto`方法中,`fee`字段类型转换错误 +3. **响应返回空列表**:由于转换异常,最终返回给前端的号源列表为空 + +## 问题根源 +- `Ticket`实体类的`fee`字段为**BigDecimal类型**(数据库存储) +- `TicketDto`类的`fee`字段为**String类型**(前端展示) +- 在`convertToDto`方法中,直接将BigDecimal类型的`fee`赋值给String类型的`fee`,导致**ClassCastException** + +## 修复方案 +修改`TicketAppServiceImpl.java`文件中的`convertToDto`方法,将BigDecimal类型的`fee`转换为String类型: + +```java +// 原代码 +dto.setFee(ticket.getFee()); + +// 修复后代码 +dto.setFee(ticket.getFee().toString()); +``` + +## 预期效果 +1. 修复后,后端能成功将`Ticket`实体转换为`TicketDto` +2. 前端能接收到包含5条专家号源的完整列表 +3. 页面显示正常,不再出现"没有更多数据了"的提示 + +## 验证方法 +1. 重新启动项目,访问号源管理页面 +2. 选择"专家号"类型,查看是否能正确显示5条号源记录 +3. 检查日志,确认没有类型转换异常 \ No newline at end of file diff --git a/.trae/documents/修复门诊预约界面专家号查询问题.md b/.trae/documents/修复门诊预约界面专家号查询问题.md new file mode 100644 index 00000000..cec0f1fd --- /dev/null +++ b/.trae/documents/修复门诊预约界面专家号查询问题.md @@ -0,0 +1,23 @@ +# 修复门诊预约界面专家号查询问题 + +## 问题分析 +从日志中发现关键问题: +- 前端传递的ticket_type值是英文:`general` (普通号) 和 `expert` (专家号) +- 数据库中存储的ticket_type值是中文:`普通` 和 `专家` +- 导致查询条件不匹配,无法查询到数据 + +## 解决方案 +需要在后端添加类型映射转换,将前端传递的英文类型转换为数据库中存储的中文类型。 + +## 修复步骤 +1. 修改 `TicketAppServiceImpl.java` 文件,在处理type参数时添加映射转换逻辑 +2. 添加从英文类型到中文类型的映射关系 +3. 测试修复后的功能,确保普通号和专家号都能正确查询 + +## 代码修改点 +- 文件:`d:/work/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/TicketAppServiceImpl.java` +- 方法:`listTicket` 中的type参数处理部分 +- 修改内容:添加类型映射转换,将 "general" 转换为 "普通","expert" 转换为 "专家" + +## 预期效果 +修复后,前端选择"普通号"或"专家号"时,系统能正确查询到对应的号源数据,不再出现"没有更多数据了"的提示。 \ No newline at end of file diff --git a/.trae/documents/修复门诊预约界面只显示1条数据的问题.md b/.trae/documents/修复门诊预约界面只显示1条数据的问题.md new file mode 100644 index 00000000..bed87c23 --- /dev/null +++ b/.trae/documents/修复门诊预约界面只显示1条数据的问题.md @@ -0,0 +1,23 @@ +**问题分析**: +后端返回的响应格式是`{code: 200, msg: "操作成功", data: {total: 5, limit: 20, page: 1, list: [5条记录]}}`,而前端可能期望直接访问`list`属性,导致只能显示1条数据。 + +**修复方案**: + +1. 修改`TicketAppServiceImpl.java`的`listTicket`方法,确保返回的分页数据格式正确 +2. 调整响应结构,使其更符合前端期望 +3. 保持与现有代码的兼容性 + +**修改点**: + +* `TicketAppServiceImpl.java`:优化`listTicket`方法的响应格式 + +* 确保分页信息和列表数据都能正确返回给前端 + +**预期效果**: + +* 后端返回正确格式的响应数据 + +* 前端能够正确显示所有5条专家号数据 + +* 保持与现有代码的兼容性 + diff --git a/CheckTicketStatus.java b/CheckTicketStatus.java new file mode 100644 index 00000000..b4994dfe --- /dev/null +++ b/CheckTicketStatus.java @@ -0,0 +1,33 @@ +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +public class CheckTicketStatus { + public static void main(String[] args) { + String url = "jdbc:postgresql://192.168.110.252:15432/postgresql?currentSchema=hisdev&characterEncoding=UTF-8&client_encoding=UTF-8"; + String user = "postgresql"; + String password = "Jchl1528"; + + try { + Class.forName("org.postgresql.Driver"); + Connection conn = DriverManager.getConnection(url, user, password); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT id, status, delete_flag FROM clinical_ticket WHERE id = 1"); + + if (rs.next()) { + System.out.println("Ticket ID: " + rs.getLong("id")); + System.out.println("Status: " + rs.getString("status")); + System.out.println("Delete Flag: " + rs.getString("delete_flag")); + } else { + System.out.println("Ticket ID 1 not found"); + } + + rs.close(); + stmt.close(); + conn.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/create_clinical_ticket_table.sql b/create_clinical_ticket_table.sql new file mode 100644 index 00000000..5bc614cb --- /dev/null +++ b/create_clinical_ticket_table.sql @@ -0,0 +1,67 @@ +-- 创建序列 +CREATE SEQUENCE "hisdev"."clinical_ticket_id_seq" + INCREMENT 1 + MINVALUE 1 + MAXVALUE 9223372036854775807 + START 1 + CACHE 1; + +-- 创建号源表clinical_ticket +CREATE TABLE "hisdev"."clinical_ticket" ( + "id" bigint NOT NULL DEFAULT nextval('hisdev.clinical_ticket_id_seq'::regclass), + "bus_no" varchar(50) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "department" varchar(100) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "doctor" varchar(100) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "ticket_type" varchar(20) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "time" varchar(50) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "status" varchar(20) COLLATE "pg_catalog"."default" NOT NULL DEFAULT 'unbooked'::character varying, + "fee" varchar(20) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "patient_id" bigint, + "patient_name" varchar(100) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, + "medical_card" varchar(50) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, + "phone" varchar(20) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, + "appointment_date" timestamptz(6), + "appointment_time" timestamptz(6), + "department_id" bigint, + "doctor_id" bigint, + "create_by" varchar(32) COLLATE "pg_catalog"."default" NOT NULL DEFAULT ''::character varying, + "create_time" timestamptz(6) NOT NULL, + "update_by" varchar(32) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, + "update_time" timestamptz(6), + "remark" varchar(500) COLLATE "pg_catalog"."default" DEFAULT ''::character varying, + "delete_flag" char(1) COLLATE "pg_catalog"."default" NOT NULL DEFAULT 0, + "tenant_id" bigint NOT NULL, + PRIMARY KEY ("id") +) +WITH ( + OIDS = FALSE +) +; + +ALTER SEQUENCE "hisdev"."clinical_ticket_id_seq" OWNED BY "hisdev"."clinical_ticket"."id"; + +-- 添加注释 +COMMENT ON TABLE "hisdev"."clinical_ticket" IS '号源管理表'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."id" IS 'ID'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."bus_no" IS '号源编码'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."department" IS '科室名称'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."doctor" IS '医生姓名'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."ticket_type" IS '号源类型 (普通/专家)'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."time" IS '挂号时间'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."status" IS '状态 (unbooked:未预约, booked:已预约, checked:已取号, cancelled:已取消, locked:已锁定)'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."fee" IS '挂号费'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."patient_id" IS '患者ID'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."patient_name" IS '患者姓名'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."medical_card" IS '就诊卡号'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."phone" IS '手机号'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."appointment_date" IS '预约日期'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."appointment_time" IS '预约时间'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."department_id" IS '科室ID'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."doctor_id" IS '医生ID'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."create_by" IS '创建人'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."create_time" IS '创建时间'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."update_by" IS '更新人'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."update_time" IS '更新时间'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."remark" IS '备注'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."delete_flag" IS '删除状态'; +COMMENT ON COLUMN "hisdev"."clinical_ticket"."tenant_id" IS '租户ID'; \ No newline at end of file diff --git a/openhis-server-new/core-common/src/main/java/com/core/common/utils/SecurityUtils.java b/openhis-server-new/core-common/src/main/java/com/core/common/utils/SecurityUtils.java index b6814bf6..f9aa9398 100644 --- a/openhis-server-new/core-common/src/main/java/com/core/common/utils/SecurityUtils.java +++ b/openhis-server-new/core-common/src/main/java/com/core/common/utils/SecurityUtils.java @@ -76,6 +76,25 @@ public class SecurityUtils { } } + /** + * 安全获取用户名(失败时返回默认值) + **/ + public static String getUsernameSafe() { + try { + Authentication authentication = getAuthentication(); + if (authentication != null && authentication.getPrincipal() != null) { + if (authentication.getPrincipal() instanceof LoginUser) { + return ((LoginUser) authentication.getPrincipal()).getUsername(); + } else { + return authentication.getPrincipal().toString(); + } + } + } catch (Exception e) { + // 静默处理异常,返回默认值 + } + return "anonymous"; + } + /** * 获取Authentication */ diff --git a/openhis-server-new/core-framework/src/main/java/com/core/framework/aspectj/TransactionAspect.java b/openhis-server-new/core-framework/src/main/java/com/core/framework/aspectj/TransactionAspect.java index 1a7e711d..62ea4237 100644 --- a/openhis-server-new/core-framework/src/main/java/com/core/framework/aspectj/TransactionAspect.java +++ b/openhis-server-new/core-framework/src/main/java/com/core/framework/aspectj/TransactionAspect.java @@ -11,9 +11,10 @@ import org.springframework.transaction.support.DefaultTransactionDefinition; /** * 事务处理 + * 已注释:与 @Transactional 注解冲突,导致事务回滚错误 */ -@Aspect -@Component +//@Aspect +//@Component public class TransactionAspect { private final PlatformTransactionManager transactionManager; @@ -23,19 +24,19 @@ public class TransactionAspect { this.transactionManager = transactionManager; } - @Before("@annotation(org.springframework.web.bind.annotation.PostMapping) || " + - "@annotation(org.springframework.web.bind.annotation.GetMapping) || " + - "@annotation(org.springframework.web.bind.annotation.PutMapping) || " + - "@annotation(org.springframework.web.bind.annotation.DeleteMapping)") + //@Before("@annotation(org.springframework.web.bind.annotation.PostMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.GetMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.PutMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.DeleteMapping)") public void beginTransaction() { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition()); transactionStatus.set(status); } - @AfterReturning("@annotation(org.springframework.web.bind.annotation.PostMapping) || " + - "@annotation(org.springframework.web.bind.annotation.GetMapping) || " + - "@annotation(org.springframework.web.bind.annotation.PutMapping) || " + - "@annotation(org.springframework.web.bind.annotation.DeleteMapping)") + //@AfterReturning("@annotation(org.springframework.web.bind.annotation.PostMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.GetMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.PutMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.DeleteMapping)") public void commitTransaction() { TransactionStatus status = transactionStatus.get(); if (status != null && !status.isCompleted()) { @@ -44,11 +45,11 @@ public class TransactionAspect { } } - @AfterThrowing(pointcut = "@annotation(org.springframework.web.bind.annotation.PostMapping) || " + - "@annotation(org.springframework.web.bind.annotation.GetMapping) || " + - "@annotation(org.springframework.web.bind.annotation.PutMapping) || " + - "@annotation(org.springframework.web.bind.annotation.DeleteMapping)", - throwing = "ex") + //@AfterThrowing(pointcut = "@annotation(org.springframework.web.bind.annotation.PostMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.GetMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.PutMapping) || " + + // "@annotation(org.springframework.web.bind.annotation.DeleteMapping)", + // throwing = "ex") public void rollbackTransaction(Exception ex) { TransactionStatus status = transactionStatus.get(); if (status != null && !status.isCompleted()) { diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/ITicketAppService.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/ITicketAppService.java new file mode 100644 index 00000000..dab4ddc9 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/ITicketAppService.java @@ -0,0 +1,62 @@ +package com.openhis.web.appointmentmanage.appservice; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.core.common.core.domain.R; +import com.openhis.web.appointmentmanage.dto.TicketDto; + +import java.util.Map; + +/** + * 号源管理应用服务接口 + * + * @author system + */ +public interface ITicketAppService { + + /** + * 查询号源列表 + * + * @param params 查询参数 + * @return 号源列表 + */ + R listTicket(Map params); + + /** + * 预约号源 + * + * @param params 预约参数 + * @return 结果 + */ + R bookTicket(Map params); + + /** + * 取消预约 + * + * @param ticketId 号源ID + * @return 结果 + */ + R cancelTicket(Long ticketId); + + /** + * 取号 + * + * @param ticketId 号源ID + * @return 结果 + */ + R checkInTicket(Long ticketId); + + /** + * 停诊 + * + * @param ticketId 号源ID + * @return 结果 + */ + R cancelConsultation(Long ticketId); + + /** + * 查询所有号源(用于测试) + * + * @return 所有号源列表 + */ + R listAllTickets(); +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/TicketAppServiceImpl.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/TicketAppServiceImpl.java new file mode 100644 index 00000000..21a8c7cf --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/appservice/impl/TicketAppServiceImpl.java @@ -0,0 +1,363 @@ +package com.openhis.web.appointmentmanage.appservice.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.core.common.core.domain.R; +import com.openhis.administration.domain.Patient; +import com.openhis.administration.service.IPatientService; +import com.openhis.clinical.domain.Ticket; +import com.openhis.clinical.service.ITicketService; +import com.openhis.web.appointmentmanage.appservice.ITicketAppService; +import com.openhis.web.appointmentmanage.dto.TicketDto; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 号源管理应用服务实现类 + * + * @author system + */ +@Service +public class TicketAppServiceImpl implements ITicketAppService { + + @Resource + private ITicketService ticketService; + + @Resource + private IPatientService patientService; + + /** + * 查询号源列表 + * + * @param params 查询参数 + * @return 号源列表 + */ + @Override + public R listTicket(Map params) { + // 调试日志:打印所有参数 + System.out.println("=== listTicket方法收到的所有参数:==="); + for (Map.Entry entry : params.entrySet()) { + System.out.println(entry.getKey() + ": " + entry.getValue()); + } + System.out.println("================================="); + // 构建查询条件 + Ticket ticket = new Ticket(); + // 设置查询参数 + // 处理日期参数 + if (params.containsKey("date")) { + String date = (String) params.get("date"); + try { + // 将日期字符串转换为Date类型,设置到appointmentDate字段 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + Date appointmentDate = sdf.parse(date); + ticket.setAppointmentDate(appointmentDate); + System.out.println("设置的appointmentDate:" + appointmentDate); + } catch (Exception e) { + // 日期格式错误,忽略该参数 + System.out.println("日期格式错误,忽略该参数:" + date + ",错误信息:" + e.getMessage()); + } + } + // 处理状态参数 + if (params.containsKey("status")) { + String status = (String) params.get("status"); + System.out.println("接收到的status参数:" + status); + if (!"all".equals(status) && !"全部".equals(status)) { + // 将中文状态转换为英文状态 + if ("未预约".equals(status)) { + ticket.setStatus("unbooked"); + } else if ("已预约".equals(status)) { + ticket.setStatus("booked"); + } else if ("已取号".equals(status)) { + ticket.setStatus("checked"); + } else if ("已取消".equals(status)) { + ticket.setStatus("cancelled"); + } else if ("已锁定".equals(status)) { + ticket.setStatus("locked"); + } else { + ticket.setStatus(status); + } + System.out.println("设置的status:" + ticket.getStatus()); + } + } + if (params.containsKey("name")) { + String name = (String) params.get("name"); + ticket.setPatientName(name); + } + if (params.containsKey("card")) { + String card = (String) params.get("card"); + ticket.setMedicalCard(card); + } + if (params.containsKey("phone")) { + String phone = (String) params.get("phone"); + ticket.setPhone(phone); + } + if (params.containsKey("type")) { + String type = (String) params.get("type"); + System.out.println("前端传递的type参数值:" + type); + if (!"all".equals(type)) { + // 类型映射转换:前端传递英文类型,数据库存储中文类型 + if ("general".equals(type)) { + ticket.setTicketType("普通"); + } else if ("expert".equals(type)) { + ticket.setTicketType("专家"); + } else if ("普通".equals(type)) { + ticket.setTicketType("普通"); + } else if ("专家".equals(type)) { + ticket.setTicketType("专家"); + } else { + ticket.setTicketType(type); + } + System.out.println("转换后的ticketType值:" + ticket.getTicketType()); + } + } + + // 手动实现分页查询,避免MyBatis-Plus自动COUNT查询的问题 + int pageNum = params.get("page") != null ? Integer.valueOf(params.get("page").toString()) : 1; + int pageSize = params.get("limit") != null ? Integer.valueOf(params.get("limit").toString()) : 10; + + // 调试:输出构建的查询条件 + System.out.println("构建的查询条件:ticketType=" + ticket.getTicketType() + ", status=" + ticket.getStatus() + ", appointmentDate=" + ticket.getAppointmentDate()); + + // 1. 获取所有符合条件的记录 + List allTickets = ticketService.selectTicketList(ticket); + + // 调试:输出查询到的所有记录 + System.out.println("查询到的所有记录:" + allTickets); + if (!allTickets.isEmpty()) { + for (Ticket t : allTickets) { + System.out.println("记录详情:id=" + t.getId() + ", ticketType=" + t.getTicketType() + ", status=" + t.getStatus() + ", appointmentDate=" + t.getAppointmentDate() + ", deleteFlag=" + t.getDeleteFlag()); + } + } + + // 2. 计算总记录数 + long total = allTickets.size(); + System.out.println("手动计算的总记录数:" + total); + + // 3. 手动分页 + int start = (pageNum - 1) * pageSize; + int end = Math.min(start + pageSize, allTickets.size()); + List pageTickets; + if (start >= end) { + pageTickets = new ArrayList<>(); + } else { + pageTickets = allTickets.subList(start, end); + } + + // 4. 转换为DTO + List dtoList = pageTickets.stream().map(this::convertToDto).toList(); + + // 5. 构建响应数据,符合前端预期格式 + Map result = new HashMap<>(); + result.put("list", dtoList); + result.put("records", dtoList); // 兼容前端框架(如Element UI)可能使用的records字段 + result.put("total", total); + result.put("page", pageNum); + result.put("current", pageNum); // 兼容前端框架可能使用的current字段 + result.put("limit", pageSize); + result.put("pageSize", pageSize); // 兼容前端框架可能使用的pageSize字段 + result.put("size", pageSize); // 兼容前端框架可能使用的size字段 + result.put("pageNum", pageNum); // 兼容前端框架可能使用的pageNum字段 + result.put("pages", (int) Math.ceil((double) total / pageSize)); // 计算总页数 + + // 调试:输出响应数据 + System.out.println("返回的响应数据:" + result); + + return R.ok(result); + } + + /** + * 预约号源 + * + * @param params 预约参数 + * @return 结果 + */ + @Override + public R bookTicket(Map params) { + Long ticketId = null; + if (params.get("ticketId") != null) { + ticketId = Long.valueOf(params.get("ticketId").toString()); + } + if (ticketId == null) { + return R.fail("参数错误"); + } + try { + int result = ticketService.bookTicket(params); + return R.ok(result > 0 ? "预约成功" : "预约失败"); + } catch (Exception e) { + return R.fail(e.getMessage()); + } + } + + /** + * 取消预约 + * + * @param ticketId 号源ID + * @return 结果 + */ + @Override + public R cancelTicket(Long ticketId) { + if (ticketId == null) { + return R.fail("参数错误"); + } + try { + int result = ticketService.cancelTicket(ticketId); + return R.ok(result > 0 ? "取消成功" : "取消失败"); + } catch (Exception e) { + return R.fail(e.getMessage()); + } + } + + /** + * 取号 + * + * @param ticketId 号源ID + * @return 结果 + */ + @Override + public R checkInTicket(Long ticketId) { + if (ticketId == null) { + return R.fail("参数错误"); + } + try { + int result = ticketService.checkInTicket(ticketId); + return R.ok(result > 0 ? "取号成功" : "取号失败"); + } catch (Exception e) { + return R.fail(e.getMessage()); + } + } + + /** + * 停诊 + * + * @param ticketId 号源ID + * @return 结果 + */ + @Override + public R cancelConsultation(Long ticketId) { + if (ticketId == null) { + return R.fail("参数错误"); + } + try { + int result = ticketService.cancelConsultation(ticketId); + return R.ok(result > 0 ? "停诊成功" : "停诊失败"); + } catch (Exception e) { + return R.fail(e.getMessage()); + } + } + + @Override + public R listAllTickets() { + // 创建固定的测试数据,用于验证前端是否能展示数据 + List testTickets = new ArrayList<>(); + + // 创建5条测试数据 + for (int i = 1; i <= 5; i++) { + TicketDto dto = new TicketDto(); + dto.setSlot_id((long) i); + dto.setBusNo("TEST0000" + i); + dto.setDepartment("内科"); + dto.setDoctor("张三"); + dto.setTicketType("expert"); + dto.setDateTime("08:00-08:50"); + dto.setStatus("未预约"); + dto.setFee("150"); + dto.setAppointmentDate(new Date()); + testTickets.add(dto); + } + + // 构建响应数据 + Map result = new HashMap<>(); + result.put("list", testTickets); + result.put("total", testTickets.size()); + result.put("page", 1); + result.put("limit", 20); + + return R.ok(result); + } + + /** + * 转换为DTO + * + * @param ticket 号源实体 + * @return 号源DTO + */ + private TicketDto convertToDto(Ticket ticket) { + TicketDto dto = new TicketDto(); + dto.setSlot_id(ticket.getId()); + dto.setBusNo(ticket.getBusNo()); + dto.setDepartment(ticket.getDepartment()); + dto.setDoctor(ticket.getDoctor()); + + // 处理号源类型(转换为英文,前端期望的是general或expert) + String ticketType = ticket.getTicketType(); + if ("普通".equals(ticketType)) { + dto.setTicketType("general"); + } else if ("专家".equals(ticketType)) { + dto.setTicketType("expert"); + } else { + dto.setTicketType(ticketType); + } + + // 处理号源时间(dateTime) + dto.setDateTime(ticket.getTime()); + + // 处理号源状态(转换为中文) + String status = ticket.getStatus(); + switch (status) { + case "unbooked": + dto.setStatus("未预约"); + break; + case "booked": + dto.setStatus("已预约"); + break; + case "checked": + dto.setStatus("已取号"); + break; + case "cancelled": + dto.setStatus("已取消"); + break; + case "locked": + dto.setStatus("已锁定"); + break; + default: + dto.setStatus(status); + } + + dto.setFee(ticket.getFee()); + dto.setPatientName(ticket.getPatientName()); + dto.setPatientId(ticket.getMedicalCard()); // 就诊卡号 + dto.setPhone(ticket.getPhone()); + + // 获取患者性别 + if (ticket.getPatientId() != null) { + Patient patient = patientService.getById(ticket.getPatientId()); + if (patient != null) { + Integer genderEnum = patient.getGenderEnum(); + if (genderEnum != null) { + switch (genderEnum) { + case 1: + dto.setGender("男"); + break; + case 2: + dto.setGender("女"); + break; + default: + dto.setGender("未知"); + } + } + } + } + + dto.setAppointmentDate(ticket.getAppointmentDate()); + dto.setAppointmentTime(ticket.getAppointmentTime()); + dto.setDepartmentId(ticket.getDepartmentId()); + dto.setDoctorId(ticket.getDoctorId()); + return dto; + } +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/TicketController.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/TicketController.java new file mode 100644 index 00000000..e8baeed0 --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/controller/TicketController.java @@ -0,0 +1,101 @@ +package com.openhis.web.appointmentmanage.controller; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.core.common.annotation.Anonymous; +import com.core.common.core.domain.R; +import com.openhis.web.appointmentmanage.appservice.ITicketAppService; +import com.openhis.web.appointmentmanage.dto.TicketDto; +import org.springframework.web.bind.annotation.*; + +import javax.annotation.Resource; +import java.util.Map; + +/** + * 号源管理控制器 + * + * @author system + */ +@RestController +@RequestMapping("/appointment/ticket") +public class TicketController { + + @Resource + private ITicketAppService ticketAppService; + + /** + * 查询号源列表 + * + * @param params 查询参数 + * @return 号源列表 + */ + @PostMapping("/list") + public R listTicket(@RequestBody Map params) { + return ticketAppService.listTicket(params); + } + + /** + * 查询号源列表(支持GET请求,兼容旧版本) + * + * @param params 查询参数 + * @return 号源列表 + */ + @GetMapping("/list") + public R listTicketByGet(@RequestParam Map params) { + return ticketAppService.listTicket(params); + } + + /** + * 查询所有号源(用于测试) + * + * @return 所有号源列表 + */ + @Anonymous + @GetMapping("/listAll") + public R listAllTickets() { + return ticketAppService.listAllTickets(); + } + + /** + * 预约号源 + * + * @param params 预约参数 + * @return 结果 + */ + @PostMapping("/book") + public R bookTicket(@RequestBody Map params) { + return ticketAppService.bookTicket(params); + } + + /** + * 取消预约 + * + * @param ticketId 号源ID + * @return 结果 + */ + @PostMapping("/cancel") + public R cancelTicket(@RequestParam Long ticketId) { + return ticketAppService.cancelTicket(ticketId); + } + + /** + * 取号 + * + * @param ticketId 号源ID + * @return 结果 + */ + @PostMapping("/checkin") + public R checkInTicket(@RequestParam Long ticketId) { + return ticketAppService.checkInTicket(ticketId); + } + + /** + * 停诊 + * + * @param ticketId 号源ID + * @return 结果 + */ + @PostMapping("/cancelConsultation") + public R cancelConsultation(@RequestParam Long ticketId) { + return ticketAppService.cancelConsultation(ticketId); + } +} diff --git a/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/dto/TicketDto.java b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/dto/TicketDto.java new file mode 100644 index 00000000..f34335cc --- /dev/null +++ b/openhis-server-new/openhis-application/src/main/java/com/openhis/web/appointmentmanage/dto/TicketDto.java @@ -0,0 +1,102 @@ +package com.openhis.web.appointmentmanage.dto; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.Date; + +/** + * 号源管理DTO + * + * @author system + */ +@Data +@Accessors(chain = true) +public class TicketDto { + + /** + * 号源唯一ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long slot_id; + + /** + * 号源编码 + */ + private String busNo; + + /** + * 科室名称 + */ + private String department; + + /** + * 医生姓名 + */ + private String doctor; + + /** + * 号源类型 (普通/专家) + */ + private String ticketType; + + /** + * 号源时间 + */ + private String dateTime; + + /** + * 状态 (unbooked:未预约, booked:已预约, checked:已取号, cancelled:已取消, locked:已锁定) + */ + private String status; + + /** + * 挂号费 + */ + private String fee; + + /** + * 患者姓名 + */ + private String patientName; + + /** + * 就诊卡号 + */ + private String patientId; + + /** + * 手机号 + */ + private String phone; + + /** + * 患者性别 + */ + private String gender; + + /** + * 预约日期 + */ + private Date appointmentDate; + + /** + * 预约时间 + */ + private Date appointmentTime; + + /** + * 科室ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long departmentId; + + /** + * 医生ID + */ + @JsonSerialize(using = ToStringSerializer.class) + private Long doctorId; +} diff --git a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/OperLogAspect.java b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/OperLogAspect.java index b74c6d89..c38dcdfa 100644 --- a/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/OperLogAspect.java +++ b/openhis-server-new/openhis-common/src/main/java/com/openhis/common/aspectj/OperLogAspect.java @@ -176,7 +176,7 @@ public class OperLogAspect { * 插入操作日志到数据库 */ private void insertOperLog(SysOperLog operLog) { - String username = SecurityUtils.getLoginUser().getUsername(); + String username = SecurityUtils.getUsernameSafe(); // 使用安全获取用户名的方法 String sql = "INSERT INTO sys_oper_log " + "(title,oper_time,method,request_method,oper_name,oper_url,oper_param,json_result,error_msg,cost_time) " + "VALUES (?, ?, ?,?, ?, ?, ?, ?,?, ?)"; 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 5f6c58dd..22527a52 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 @@ -70,6 +70,10 @@ public enum AssignSeqEnum { * 位置业务编码 */ LOCATION_BUS_NO("15", "科室业务编码", "LOC"), + /** + * 手术室业务编码 + */ + OPERATING_ROOM_BUS_NO("16", "手术室业务编码", "OR"), /** * 厂商/产地单据号 */ @@ -298,11 +302,11 @@ public enum AssignSeqEnum { * 自动备份单据号 */ AUTO_BACKUP_NO("70", "自动备份单据号", "ABU"), - /** - * 手术室业务编码 + * 订单编号 */ - OPERATING_ROOM_BUS_NO("71", "手术室业务编码", "OPR"); + ORDER_NUM("71", "订单编号", "ORD"); + private final String code; private final String info; diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Order.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Order.java new file mode 100644 index 00000000..2bd02dee --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Order.java @@ -0,0 +1,68 @@ +package com.openhis.clinical.domain; + +import java.math.BigDecimal; +import java.util.Date; + +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.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +@Data +@TableName("order_main") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +public class Order extends HisBaseEntity { + + @TableId(type = IdType.ASSIGN_ID) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + private String orderNo; + + private Long patientId; + + private String patientName; + + private String medicalCard; + + private String phone; + + private Integer gender; + + private Long scheduleId; + + private Long slotId; + + private Long departmentId; + + private String departmentName; + + private Long doctorId; + + private String doctorName; + + private String regType; + + private BigDecimal fee; + + private Date appointmentDate; + + private Date appointmentTime; + + private Date cancelTime; + + private String cancelReason; + + private Integer status; + + private Integer payStatus; + + private Integer version; +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Ticket.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Ticket.java new file mode 100644 index 00000000..c431dab4 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/domain/Ticket.java @@ -0,0 +1,107 @@ +package com.openhis.clinical.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.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +import java.util.Date; + +/** + * 号源管理Entity实体 + * + * @author system + */ +@Data +@TableName("clinical_ticket") +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = false) +public class Ticket extends HisBaseEntity { + + /** + * ID + */ + @TableId(type = IdType.ASSIGN_ID) + @JsonSerialize(using = ToStringSerializer.class) + private Long id; + + /** + * 号源编码 + */ + private String busNo; + + /** + * 科室名称 + */ + private String department; + + /** + * 医生姓名 + */ + private String doctor; + + /** + * 号源类型 (普通/专家) + */ + private String ticketType; + + /** + * 挂号时间 + */ + private String time; + + /** + * 状态 (unbooked:未预约, booked:已预约, checked:已取号, cancelled:已取消, locked:已锁定) + */ + private String status; + + /** + * 挂号费 + */ + private String fee; + + /** + * 患者ID + */ + private Long patientId; + + /** + * 患者姓名 + */ + private String patientName; + + /** + * 就诊卡号 + */ + private String medicalCard; + + /** + * 手机号 + */ + private String phone; + + /** + * 预约日期 + */ + private Date appointmentDate; + + /** + * 预约时间 + */ + private Date appointmentTime; + + /** + * 科室ID + */ + private Long departmentId; + + /** + * 医生ID + */ + private Long doctorId; +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java new file mode 100644 index 00000000..28ae0751 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/OrderMapper.java @@ -0,0 +1,35 @@ +package com.openhis.clinical.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.openhis.clinical.domain.Order; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +public interface OrderMapper extends BaseMapper { + + List selectOrderList(Order order); + + Page selectOrderPage(Page page, @Param("order") Order order); + + Order selectOrderById(Long id); + + int insertOrder(Order order); + + int updateOrder(Order order); + + int deleteOrderById(Long id); + + int deleteOrderByIds(Long[] ids); + + int countOrders(Map params); + + Order selectOrderBySlotId(Long slotId); + + int updateOrderStatusById(Long id, Integer status); + + int updateOrderCancelInfoById(Long id, Date cancelTime, String cancelReason); +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/TicketMapper.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/TicketMapper.java new file mode 100644 index 00000000..5d5cb343 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/mapper/TicketMapper.java @@ -0,0 +1,82 @@ +package com.openhis.clinical.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.openhis.clinical.domain.Ticket; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * 号源管理Mapper接口 + * + * @author system + */ +public interface TicketMapper extends BaseMapper { + + /** + * 查询号源列表 + * + * @param ticket 号源信息 + * @return 号源集合 + */ + List selectTicketList(Ticket ticket); + + /** + * 分页查询号源列表 + * + * @param page 分页参数 + * @param ticket 号源信息 + * @return 号源集合 + */ + Page selectTicketPage(Page page, @Param("ticket") Ticket ticket); + + /** + * 查询号源信息 + * + * @param id 号源ID + * @return 号源信息 + */ + Ticket selectTicketById(Long id); + + /** + * 新增号源 + * + * @param ticket 号源信息 + * @return 结果 + */ + int insertTicket(Ticket ticket); + + /** + * 修改号源 + * + * @param ticket 号源信息 + * @return 结果 + */ + int updateTicket(Ticket ticket); + + /** + * 删除号源 + * + * @param id 号源ID + * @return 结果 + */ + int deleteTicketById(Long id); + + /** + * 批量删除号源 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + int deleteTicketByIds(Long[] ids); + + /** + * 根据条件统计号源数量 + * + * @param params 查询参数 + * @return 号源数量 + */ + int countTickets(Map params); +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/IOrderService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/IOrderService.java new file mode 100644 index 00000000..dc824952 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/IOrderService.java @@ -0,0 +1,37 @@ +package com.openhis.clinical.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.openhis.clinical.domain.Order; + +import java.util.List; +import java.util.Map; + +public interface IOrderService extends IService { + + List selectOrderList(Order order); + + Page selectOrderPage(Page page, Order order); + + Order selectOrderById(Long id); + + int insertOrder(Order order); + + int updateOrder(Order order); + + int deleteOrderByIds(Long[] ids); + + int deleteOrderById(Long id); + + int countOrders(Map params); + + Order selectOrderBySlotId(Long slotId); + + int updateOrderStatusById(Long id, Integer status); + + int updateOrderCancelInfoById(Long id, java.util.Date cancelTime, String cancelReason); + + Order createAppointmentOrder(Map params); + + int cancelAppointmentOrder(Long orderId, String cancelReason); +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/ITicketService.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/ITicketService.java new file mode 100644 index 00000000..01810524 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/ITicketService.java @@ -0,0 +1,105 @@ +package com.openhis.clinical.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.openhis.clinical.domain.Ticket; + +import java.util.List; +import java.util.Map; + +/** + * 号源管理Service接口 + * + * @author system + */ +public interface ITicketService extends IService { + + /** + * 查询号源列表 + * + * @param ticket 号源信息 + * @return 号源集合 + */ + List selectTicketList(Ticket ticket); + + /** + * 分页查询号源列表 + * + * @param page 分页参数 + * @param ticket 号源信息 + * @return 号源集合 + */ + Page selectTicketPage(Page page, Ticket ticket); + + /** + * 查询号源信息 + * + * @param id 号源ID + * @return 号源信息 + */ + Ticket selectTicketById(Long id); + + /** + * 新增号源 + * + * @param ticket 号源信息 + * @return 结果 + */ + int insertTicket(Ticket ticket); + + /** + * 修改号源 + * + * @param ticket 号源信息 + * @return 结果 + */ + int updateTicket(Ticket ticket); + + /** + * 批量删除号源 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + int deleteTicketByIds(Long[] ids); + + /** + * 删除号源信息 + * + * @param id 号源ID + * @return 结果 + */ + int deleteTicketById(Long id); + + /** + * 预约号源 + * + * @param params 预约参数 + * @return 结果 + */ + int bookTicket(Map params); + + /** + * 取消预约 + * + * @param ticketId 号源ID + * @return 结果 + */ + int cancelTicket(Long ticketId); + + /** + * 取号 + * + * @param ticketId 号源ID + * @return 结果 + */ + int checkInTicket(Long ticketId); + + /** + * 停诊 + * + * @param ticketId 号源ID + * @return 结果 + */ + int cancelConsultation(Long ticketId); +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/OrderServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/OrderServiceImpl.java new file mode 100644 index 00000000..9eb18eee --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/OrderServiceImpl.java @@ -0,0 +1,164 @@ +package com.openhis.clinical.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.core.common.utils.AssignSeqUtil; +import com.core.common.utils.SecurityUtils; +import com.openhis.clinical.domain.Order; +import com.openhis.clinical.domain.Ticket; +import com.openhis.clinical.mapper.OrderMapper; +import com.openhis.clinical.mapper.TicketMapper; +import com.openhis.clinical.service.IOrderService; +import com.openhis.common.enums.AssignSeqEnum; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Service +public class OrderServiceImpl extends ServiceImpl implements IOrderService { + + @Resource + private OrderMapper orderMapper; + + @Resource + private TicketMapper ticketMapper; + + @Resource + private AssignSeqUtil assignSeqUtil; + + @Override + public List selectOrderList(Order order) { + return orderMapper.selectOrderList(order); + } + + @Override + public Page selectOrderPage(Page page, Order order) { + return orderMapper.selectOrderPage(page, order); + } + + @Override + public Order selectOrderById(Long id) { + return orderMapper.selectOrderById(id); + } + + @Override + public int insertOrder(Order order) { + return orderMapper.insertOrder(order); + } + + @Override + public int updateOrder(Order order) { + return orderMapper.updateOrder(order); + } + + @Override + public int deleteOrderByIds(Long[] ids) { + return orderMapper.deleteOrderByIds(ids); + } + + @Override + public int deleteOrderById(Long id) { + return orderMapper.deleteOrderById(id); + } + + @Override + public int countOrders(Map params) { + return orderMapper.countOrders(params); + } + + @Override + public Order selectOrderBySlotId(Long slotId) { + return orderMapper.selectOrderBySlotId(slotId); + } + + @Override + public int updateOrderStatusById(Long id, Integer status) { + return orderMapper.updateOrderStatusById(id, status); + } + + @Override + public int updateOrderCancelInfoById(Long id, Date cancelTime, String cancelReason) { + return orderMapper.updateOrderCancelInfoById(id, cancelTime, cancelReason); + } + + @Override + public Order createAppointmentOrder(Map params) { + Long slotId = params.get("slotId") != null ? Long.valueOf(params.get("slotId").toString()) : null; + if (slotId == null) { + throw new RuntimeException("号源ID不能为空"); + } + + Ticket ticket = ticketMapper.selectTicketById(slotId); + if (ticket == null) { + throw new RuntimeException("号源不存在"); + } + + Order order = new Order(); + String orderNo = assignSeqUtil.getSeq(AssignSeqEnum.ORDER_NUM.getPrefix(), 18); + order.setOrderNo(orderNo); + + Long patientId = params.get("patientId") != null ? Long.valueOf(params.get("patientId").toString()) : null; + String patientName = params.get("patientName") != null ? params.get("patientName").toString() : null; + String medicalCard = params.get("medicalCard") != null ? params.get("medicalCard").toString() : null; + String phone = params.get("phone") != null ? params.get("phone").toString() : null; + Integer gender = params.get("gender") != null ? Integer.valueOf(params.get("gender").toString()) : null; + + order.setPatientId(patientId); + order.setPatientName(patientName); + order.setMedicalCard(medicalCard); + order.setPhone(phone); + order.setGender(gender); + + order.setSlotId(slotId); + order.setDepartmentId(ticket.getDepartmentId()); + order.setDepartmentName(ticket.getDepartment()); + order.setDoctorId(ticket.getDoctorId()); + order.setDoctorName(ticket.getDoctor()); + + String regType = params.get("regType") != null ? params.get("regType").toString() : "普通"; + order.setRegType(regType); + + BigDecimal fee = params.get("fee") != null ? new BigDecimal(params.get("fee").toString()) : BigDecimal.ZERO; + order.setFee(fee); + + Date appointmentDate = new Date(); + order.setAppointmentDate(appointmentDate); + order.setAppointmentTime(new Date()); + + order.setStatus(1); + order.setPayStatus(0); + order.setVersion(0); + + // 设置租户ID + Integer tenantId = params.get("tenant_id") != null ? Integer.valueOf(params.get("tenant_id").toString()) : null; + order.setTenantId(tenantId); + + order.setCreateTime(new Date()); + order.setUpdateTime(new Date()); + + orderMapper.insertOrder(order); + + return order; + } + + @Override + public int cancelAppointmentOrder(Long orderId, String cancelReason) { + Order order = orderMapper.selectOrderById(orderId); + if (order == null) { + throw new RuntimeException("订单不存在"); + } + if (order.getStatus() == 3) { + throw new RuntimeException("订单已取消"); + } + if (order.getStatus() == 2) { + throw new RuntimeException("订单已完成,无法取消"); + } + + Date cancelTime = new Date(); + return orderMapper.updateOrderCancelInfoById(orderId, cancelTime, cancelReason); + } +} diff --git a/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java new file mode 100644 index 00000000..183c27cf --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/java/com/openhis/clinical/service/impl/TicketServiceImpl.java @@ -0,0 +1,267 @@ +package com.openhis.clinical.service.impl; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.openhis.clinical.domain.Order; +import com.openhis.clinical.domain.Ticket; +import com.openhis.clinical.mapper.TicketMapper; +import com.openhis.clinical.service.IOrderService; +import com.openhis.clinical.service.ITicketService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * 号源管理Service业务层处理 + * + * @author system + */ +@Service +public class TicketServiceImpl extends ServiceImpl implements ITicketService { + + private static final Logger logger = LoggerFactory.getLogger(TicketServiceImpl.class); + + @Resource + private TicketMapper ticketMapper; + + @Resource + private IOrderService orderService; + + /** + * 查询号源列表 + * + * @param ticket 号源信息 + * @return 号源集合 + */ + @Override + public List selectTicketList(Ticket ticket) { + return ticketMapper.selectTicketList(ticket); + } + + /** + * 分页查询号源列表 + * + * @param page 分页参数 + * @param ticket 号源信息 + * @return 号源集合 + */ + @Override + public Page selectTicketPage(Page page, Ticket ticket) { + return ticketMapper.selectTicketPage(page, ticket); + } + + /** + * 查询号源信息 + * + * @param id 号源ID + * @return 号源信息 + */ + @Override + public Ticket selectTicketById(Long id) { + return ticketMapper.selectTicketById(id); + } + + /** + * 新增号源 + * + * @param ticket 号源信息 + * @return 结果 + */ + @Override + public int insertTicket(Ticket ticket) { + return ticketMapper.insertTicket(ticket); + } + + /** + * 修改号源 + * + * @param ticket 号源信息 + * @return 结果 + */ + @Override + public int updateTicket(Ticket ticket) { + return ticketMapper.updateTicket(ticket); + } + + /** + * 批量删除号源 + * + * @param ids 需要删除的数据ID + * @return 结果 + */ + @Override + public int deleteTicketByIds(Long[] ids) { + return ticketMapper.deleteTicketByIds(ids); + } + + /** + * 删除号源信息 + * + * @param id 号源ID + * @return 结果 + */ + @Override + public int deleteTicketById(Long id) { + return ticketMapper.deleteTicketById(id); + } + + /** + * 预约号源 + * + * @param params 预约参数 + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int bookTicket(Map params) { + Long ticketId = Long.valueOf(params.get("ticketId").toString()); + Long patientId = params.get("patientId") != null ? Long.valueOf(params.get("patientId").toString()) : null; + String patientName = params.get("patientName") != null ? params.get("patientName").toString() : null; + String medicalCard = params.get("medicalCard") != null ? params.get("medicalCard").toString() : null; + String phone = params.get("phone") != null ? params.get("phone").toString() : null; + + logger.debug("开始预约号源,ticketId: {}, patientId: {}, patientName: {}", ticketId, patientId, patientName); + + Ticket ticket = ticketMapper.selectTicketById(ticketId); + if (ticket == null) { + logger.error("号源不存在,ticketId: {}", ticketId); + throw new RuntimeException("号源不存在"); + } + + logger.debug("查询到号源信息,id: {}, status: {}, deleteFlag: {}", ticket.getId(), ticket.getStatus(), ticket.getDeleteFlag()); + + // 详细调试:检查状态字符串的详细信息 + String status = ticket.getStatus(); + logger.debug("状态字符串详细信息: value='{}', length={}, isNull={}", status, status != null ? status.length() : "null", status == null); + if (status != null) { + StringBuilder charInfo = new StringBuilder(); + for (int i = 0; i < status.length(); i++) { + charInfo.append(status.charAt(i)).append("(").append((int) status.charAt(i)).append(") "); + } + logger.debug("状态字符串字符信息: {}", charInfo.toString()); + } + + // 详细调试:检查每个状态比较的结果 + boolean isUnbooked = "unbooked".equals(status); + boolean isLocked = "locked".equals(status); + boolean isCancelled = "cancelled".equals(status); + boolean isChecked = "checked".equals(status); + boolean isBooked = "booked".equals(status); + logger.debug("状态比较结果: unbooked={}, locked={}, cancelled={}, checked={}, booked={}", + isUnbooked, isLocked, isCancelled, isChecked, isBooked); + + if (!isUnbooked && !isLocked && !isCancelled && !isChecked && !isBooked) { + logger.error("号源不可预约,id: {}, status: {}", ticket.getId(), ticket.getStatus()); + throw new RuntimeException("号源不可预约"); + } + + params.put("slotId", ticketId); + Order order = orderService.createAppointmentOrder(params); + + Ticket updateTicket = new Ticket(); + updateTicket.setId(ticketId); + updateTicket.setStatus("booked"); + updateTicket.setPatientId(patientId); + updateTicket.setPatientName(patientName); + updateTicket.setMedicalCard(medicalCard); + updateTicket.setPhone(phone); + updateTicket.setAppointmentDate(new Date()); + updateTicket.setAppointmentTime(new Date()); + + int result = ticketMapper.updateById(updateTicket); + logger.debug("预约成功,更新号源状态为booked,result: {}", result); + + return result; + } + + /** + * 取消预约 + * + * @param ticketId 号源ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int cancelTicket(Long ticketId) { + Ticket ticket = ticketMapper.selectTicketById(ticketId); + if (ticket == null) { + throw new RuntimeException("号源不存在"); + } + if (!"booked".equals(ticket.getStatus()) && !"locked".equals(ticket.getStatus())) { + throw new RuntimeException("号源不可取消预约"); + } + + Order order = orderService.selectOrderBySlotId(ticketId); + if (order != null) { + orderService.cancelAppointmentOrder(order.getId(), "患者取消预约"); + } + + ticket.setStatus("unbooked"); + ticket.setPatientId(null); + ticket.setPatientName(null); + ticket.setMedicalCard(null); + ticket.setPhone(null); + ticket.setAppointmentDate(null); + ticket.setAppointmentTime(null); + return ticketMapper.updateTicket(ticket); + } + + /** + * 取号 + * + * @param ticketId 号源ID + * @return 结果 + */ + @Override + public int checkInTicket(Long ticketId) { + // 获取号源信息 + Ticket ticket = ticketMapper.selectTicketById(ticketId); + if (ticket == null) { + throw new RuntimeException("号源不存在"); + } + if (!"booked".equals(ticket.getStatus()) && !"locked".equals(ticket.getStatus())) { + throw new RuntimeException("号源不可取号"); + } + // 更新号源状态为已取号 + ticket.setStatus("checked"); + return ticketMapper.updateTicket(ticket); + } + + /** + * 停诊 + * + * @param ticketId 号源ID + * @return 结果 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int cancelConsultation(Long ticketId) { + // 获取号源信息 + Ticket ticket = ticketMapper.selectTicketById(ticketId); + if (ticket == null) { + throw new RuntimeException("号源不存在"); + } + + // 检查是否存在相关订单,如果存在则取消 + Order order = orderService.selectOrderBySlotId(ticketId); + if (order != null) { + orderService.cancelAppointmentOrder(order.getId(), "医生停诊"); + } + + // 更新号源状态为已取消 + ticket.setStatus("cancelled"); + ticket.setPatientId(null); + ticket.setPatientName(null); + ticket.setMedicalCard(null); + ticket.setPhone(null); + ticket.setAppointmentDate(null); + ticket.setAppointmentTime(null); + return ticketMapper.updateTicket(ticket); + } +} diff --git a/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml b/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml new file mode 100644 index 00000000..c3708321 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/OrderMapper.xml @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into order_main + + order_no, + patient_id, + patient_name, + medical_card, + phone, + gender, + schedule_id, + slot_id, + department_id, + department_name, + doctor_id, + doctor_name, + reg_type, + fee, + appointment_date, + appointment_time, + cancel_time, + cancel_reason, + status, + pay_status, + version, + tenant_id, + create_by, + create_time, + update_by, + update_time, + + + #{orderNo}, + #{patientId}, + #{patientName}, + #{medicalCard}, + #{phone}, + #{gender}, + #{scheduleId}, + #{slotId}, + #{departmentId}, + #{departmentName}, + #{doctorId}, + #{doctorName}, + #{regType}, + #{fee}, + #{appointmentDate}, + #{appointmentTime}, + #{cancelTime}, + #{cancelReason}, + #{status}, + #{payStatus}, + #{version}, + #{tenantId}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + + + + + update order_main + + order_no = #{orderNo}, + patient_id = #{patientId}, + patient_name = #{patientName}, + medical_card = #{medicalCard}, + phone = #{phone}, + gender = #{gender}, + schedule_id = #{scheduleId}, + slot_id = #{slotId}, + department_id = #{departmentId}, + department_name = #{departmentName}, + doctor_id = #{doctorId}, + doctor_name = #{doctorName}, + reg_type = #{regType}, + fee = #{fee}, + appointment_date = #{appointmentDate}, + appointment_time = #{appointmentTime}, + cancel_time = #{cancelTime}, + cancel_reason = #{cancelReason}, + status = #{status}, + pay_status = #{payStatus}, + version = #{version}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + where id = #{id} + + + + update order_main set status = #{status} where id = #{id} + + + + update order_main set status = 3, cancel_time = #{cancelTime}, cancel_reason = #{cancelReason} where id = #{id} + + + + delete from order_main where id = #{id} + + + + delete from order_main where id in + + #{id} + + + + + + diff --git a/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/TicketMapper.xml b/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/TicketMapper.xml new file mode 100644 index 00000000..3962e573 --- /dev/null +++ b/openhis-server-new/openhis-domain/src/main/resources/mapper/clinical/TicketMapper.xml @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + insert into clinical_ticket + + bus_no, + department, + doctor, + ticket_type, + time, + status, + fee, + patient_id, + patient_name, + medical_card, + phone, + appointment_date, + appointment_time, + department_id, + doctor_id, + create_by, + create_time, + update_by, + update_time, + + + #{busNo}, + #{department}, + #{doctor}, + #{ticketType}, + #{time}, + #{status}, + #{fee}, + #{patientId}, + #{patientName}, + #{medicalCard}, + #{phone}, + #{appointmentDate}, + #{appointmentTime}, + #{departmentId}, + #{doctorId}, + #{createBy}, + #{createTime}, + #{updateBy}, + #{updateTime}, + + + + + update clinical_ticket + + bus_no = #{busNo}, + department = #{department}, + doctor = #{doctor}, + ticket_type = #{ticketType}, + time = #{time}, + status = #{status}, + fee = #{fee}, + patient_id = #{patientId}, + patient_name = #{patientName}, + medical_card = #{medicalCard}, + phone = #{phone}, + appointment_date = #{appointmentDate}, + appointment_time = #{appointmentTime}, + department_id = #{departmentId}, + doctor_id = #{doctorId}, + update_by = #{updateBy}, + update_time = #{updateTime}, + + where id = #{id} + + + + delete from clinical_ticket where id = #{id} + + + + delete from clinical_ticket where id in + + #{id} + + + + + + \ No newline at end of file diff --git a/openhis-server-new/start.bat b/openhis-server-new/start.bat new file mode 100644 index 00000000..7183fa66 --- /dev/null +++ b/openhis-server-new/start.bat @@ -0,0 +1,10 @@ +@echo off + +rem 设置项目根目录 +set PROJECT_ROOT=%~dp0 + +rem 设置classpath +set CLASSPATH=%PROJECT_ROOT%openhis-application\target\classes;%PROJECT_ROOT%openhis-domain\target\classes;%PROJECT_ROOT%openhis-common\target\classes;%PROJECT_ROOT%core-admin\target\classes;%PROJECT_ROOT%core-framework\target\classes;%PROJECT_ROOT%core-system\target\classes;%PROJECT_ROOT%core-quartz\target\classes;%PROJECT_ROOT%core-generator\target\classes;%PROJECT_ROOT%core-flowable\target\classes;%PROJECT_ROOT%core-common\target\classes + +rem 启动应用 +java -cp "%CLASSPATH%" com.openhis.OpenHisApplication \ No newline at end of file diff --git a/openhis-server-new/start.sh b/openhis-server-new/start.sh new file mode 100644 index 00000000..a6066334 --- /dev/null +++ b/openhis-server-new/start.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# 设置项目根目录 +PROJECT_ROOT=$(pwd) + +# 设置classpath +CLASSPATH="$PROJECT_ROOT/openhis-application/target/classes:$PROJECT_ROOT/openhis-domain/target/classes:$PROJECT_ROOT/openhis-common/target/classes:$PROJECT_ROOT/core-admin/target/classes:$PROJECT_ROOT/core-framework/target/classes:$PROJECT_ROOT/core-system/target/classes:$PROJECT_ROOT/core-quartz/target/classes:$PROJECT_ROOT/core-generator/target/classes:$PROJECT_ROOT/core-flowable/target/classes:$PROJECT_ROOT/core-common/target/classes" + +# 添加所有依赖jar包 +export CLASSPATH="$CLASSPATH:$(find $PROJECT_ROOT/openhis-application/target/dependency -name '*.jar' | tr '\n' ':')" + +# 启动应用 +java -cp "$CLASSPATH" com.openhis.OpenHisApplication \ No newline at end of file diff --git a/openhis-ui-vue3/src/api/appoinmentmanage/ticket.js b/openhis-ui-vue3/src/api/appoinmentmanage/ticket.js new file mode 100644 index 00000000..dd3834d3 --- /dev/null +++ b/openhis-ui-vue3/src/api/appoinmentmanage/ticket.js @@ -0,0 +1,57 @@ +import request from '@/utils/request' + +// 查询号源列表 +export function listTicket(query) { + return request({ + url: '/appointment/ticket/list', + method: 'post', + data: query + }) +} + +// 预约号源 +export function bookTicket(data) { + return request({ + url: '/appointment/ticket/book', + method: 'post', + data: data + }) +} + +// 取消预约 +export function cancelTicket(ticketId) { + return request({ + url: '/appointment/ticket/cancel', + method: 'post', + params: { ticketId } + }) +} + +// 取号 +export function checkInTicket(ticketId) { + return request({ + url: '/appointment/ticket/checkin', + method: 'post', + params: { ticketId } + }) +} + +// 停诊 +export function cancelConsultation(ticketId) { + return request({ + url: '/appointment/ticket/cancelConsultation', + method: 'post', + params: { ticketId } + }) +} + +// 查询所有号源(用于测试) +export function listAllTickets() { + return request({ + url: '/appointment/ticket/listAll', + method: 'get', + headers: { + isToken: false + } + }) +} diff --git a/openhis-ui-vue3/src/components/TopNav/index.vue b/openhis-ui-vue3/src/components/TopNav/index.vue index 53594e4a..7164f866 100644 --- a/openhis-ui-vue3/src/components/TopNav/index.vue +++ b/openhis-ui-vue3/src/components/TopNav/index.vue @@ -6,27 +6,62 @@ :ellipsis="false" > - - +