Compare commits
29 Commits
fix/BUG#61
...
guanyu
| Author | SHA1 | Date | |
|---|---|---|---|
| 920752d36b | |||
| 6dc2a715c8 | |||
| bd50c58dd4 | |||
| e23ac2fd09 | |||
| 4e3ee1f49d | |||
| 2135682332 | |||
| 4ac9254496 | |||
| d4bbc58e4e | |||
| aa193f60a2 | |||
| b74f6bf3f9 | |||
| 9f789cd3a3 | |||
| 4c1222f0f4 | |||
| cfa073bdba | |||
| 021f7180c0 | |||
|
|
ee59fd5ea0 | ||
| 20a372268b | |||
| 31f288c0dd | |||
| 5c97380a78 | |||
| 30e5c92f0b | |||
| 7c6e35dcc3 | |||
| 74b67401f3 | |||
| 81d954fceb | |||
| 7adb3b3ea4 | |||
| 1e6704928a | |||
| 75e49f0237 | |||
| 2b6b00b6c2 | |||
| 1ddf8a2ccd | |||
| 0a37b05aab | |||
| 20817d6dc4 |
44
bug444_analysis.md
Normal file
44
bug444_analysis.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Bug #444 分析报告
|
||||||
|
|
||||||
|
## Bug 描述
|
||||||
|
【手术管理-门诊手术安排】生成临时医嘱界面,"已引用计费药品"列表未正常显示药品详细名称信息,且错误地带出了非药品类的计费信息(如手术诊疗项目"小腿烧伤扩创交腿皮瓣修复术"、检查项目"心脏彩色多普勒超声")。
|
||||||
|
|
||||||
|
## 根因分析
|
||||||
|
|
||||||
|
### 数据流
|
||||||
|
1. 用户点击"医嘱"按钮 → `handleMedicalAdvice()` → 调用 `getPrescriptionList()` 获取计费数据
|
||||||
|
2. 用户对数据进行过滤后展示在"已引用计费药品"列表
|
||||||
|
3. 用户点击"引用计费"按钮 → `handleQuoteBilling()` → 再次调用 `getPrescriptionList()` 获取最新计费数据
|
||||||
|
|
||||||
|
### 根因定位
|
||||||
|
**`handleQuoteBilling()` 方法(index.vue:1866-1877)缺少非药品关键词过滤逻辑。**
|
||||||
|
|
||||||
|
`handleMedicalAdvice()` 中有两层过滤:
|
||||||
|
1. `adviceType !== 1` 过滤(只保留药品类型)
|
||||||
|
2. **关键词排除过滤**(排除名称中包含"术"、"超声"、"检查"等非药品关键词的项目)
|
||||||
|
|
||||||
|
但 `handleQuoteBilling()` 中只有第一层过滤(`adviceType !== 1`),**缺少关键词排除过滤**。
|
||||||
|
|
||||||
|
当后端返回的计费数据中某些非药品项目被错误标注为 `adviceType=1` 时:
|
||||||
|
- `handleMedicalAdvice()` 能通过关键词过滤排除这些项目
|
||||||
|
- `handleQuoteBilling()` 无法排除,导致非药品项目出现在"已引用计费药品"列表中
|
||||||
|
|
||||||
|
### 代码对比
|
||||||
|
|
||||||
|
| 过滤条件 | handleMedicalAdvice (L1576-1597) | handleQuoteBilling (L1866-1877) |
|
||||||
|
|---------|:---:|:---:|
|
||||||
|
| encounterId 匹配 | ✓ | ✓ |
|
||||||
|
| adviceType === 1 | ✓ | ✓ |
|
||||||
|
| 名称非空 | ✓ | ✓ |
|
||||||
|
| **关键词排除** | ✓ **有** | ✗ **缺失** |
|
||||||
|
| requestId 过滤 | ✓ | ✓ |
|
||||||
|
|
||||||
|
## 修复方案
|
||||||
|
|
||||||
|
在 `handleQuoteBilling()` 方法的过滤逻辑中,添加与 `handleMedicalAdvice()` 一致的关键词排除逻辑:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 🔧 修复 Bug #444: 排除名称中包含手术/检查/诊疗关键词的非药品项目
|
||||||
|
const excludedKeywords = ['术', '超声', '多普勒', '检查', '检验', '彩超', 'X线', 'CT', 'MRI', '扫描', '造影'];
|
||||||
|
if (excludedKeywords.some(kw => medicineName.includes(kw))) return false;
|
||||||
|
```
|
||||||
@@ -5,37 +5,39 @@
|
|||||||
|
|
||||||
## 根因定位
|
## 根因定位
|
||||||
|
|
||||||
**核心问题在 `OrganizationLocationAppServiceImpl.java:161-174`**
|
**核心问题在 `OrganizationLocationAppServiceImpl.java:161-162`**
|
||||||
|
|
||||||
时间冲突检测的查询逻辑存在两个缺陷:
|
时间冲突检测使用了 `getOrgLocListByActivityDefinitionId()` 跨科室查询同一诊疗定义下的**所有**科室配置记录。
|
||||||
|
|
||||||
|
### 缺陷:跨科室误报冲突
|
||||||
|
|
||||||
### 缺陷1:查询范围过窄
|
|
||||||
```java
|
```java
|
||||||
// 只查同一科室 + 同一诊疗的记录
|
// 修复前:查询同一诊疗的所有科室配置(跨科室)
|
||||||
getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getOrganizationId(), orgLoc.getActivityDefinitionId());
|
organizationLocationService.getOrgLocListByActivityDefinitionId(orgLoc.getActivityDefinitionId());
|
||||||
```
|
```
|
||||||
只查询**同一科室**的记录。如果同一诊疗项目在其他科室已有配置且时间重叠,不会被当前查询检测到。但系统本应阻止同一诊疗在多个科室同时段执行。
|
|
||||||
|
|
||||||
### 缺陷2:"未知科室"错误提示
|
该查询返回**所有科室**中同一诊疗项目的配置记录。当其他科室(非当前操作科室)已配置了相同诊疗且时间重叠时,会被误判为冲突。
|
||||||
|
|
||||||
|
"执行科室配置"的业务语义是:为某个科室配置它可执行的诊疗项目及时段。不同科室配置同一诊疗的不同时段是完全合理的(如检验科 08:00-12:00,放射科 14:00-18:00)。跨科室时间重叠不应视为冲突。
|
||||||
|
|
||||||
|
### 附带缺陷:"未知科室"错误提示
|
||||||
当冲突记录关联的科室被软删除(`delete_flag='1'`)时,`organizationService.getById()` 受 `@TableLogic` 注解影响查不到该科室,返回 null,错误提示变成"与未知科室时间冲突"。
|
当冲突记录关联的科室被软删除(`delete_flag='1'`)时,`organizationService.getById()` 受 `@TableLogic` 注解影响查不到该科室,返回 null,错误提示变成"与未知科室时间冲突"。
|
||||||
|
|
||||||
数据库验证发现确实存在软删除科室的组织位置记录(内科门诊、上海学校医院、信息科等,共9条)。
|
|
||||||
|
|
||||||
### 数据流
|
|
||||||
|
|
||||||
1. 前端选择科室 → 点击"添加新项目" → 填写诊疗和时间 → 点击"保存"
|
|
||||||
2. 后端 `addOrEditOrgLoc()` 接收请求
|
|
||||||
3. 查询现有冲突记录(**当前只查同科室**)
|
|
||||||
4. 对冲突记录检查时间重叠
|
|
||||||
5. 查找冲突科室名称 → 若科室被软删除则返回 null → "未知科室"
|
|
||||||
|
|
||||||
## 修复方案
|
## 修复方案
|
||||||
|
|
||||||
1. **修改冲突检测范围**:查询同一 `activityDefinitionId` 的所有记录(跨科室检测),而非仅限当前科室
|
**修改冲突检测范围**:将 `getOrgLocListByActivityDefinitionId` 改为 `getOrgLocListByOrgIdAndActivityDefinitionId`,仅检测**同一科室内**的时间冲突。
|
||||||
2. **优雅处理"未知科室"**:当 `getById` 返回 null 时,使用 "已删除科室( ID )" 替代 "未知科室",提供更有用的信息
|
|
||||||
3. **新增 Service 方法**:`getOrgLocListByActivityDefinitionId(Long activityDefinitionId)` 用于按诊疗定义查询所有记录
|
|
||||||
|
|
||||||
## 涉及文件
|
## 修复结果
|
||||||
- `openhis-server-new/openhis-application/src/main/java/com/openhis/web/basedatamanage/appservice/impl/OrganizationLocationAppServiceImpl.java`
|
|
||||||
- `openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/IOrganizationLocationService.java`
|
**修复状态**: ✅ 成功
|
||||||
- `openhis-server-new/openhis-domain/src/main/java/com/openhis/administration/service/impl/OrganizationLocationServiceImpl.java`
|
|
||||||
|
**改动行数**: +3/-1(`OrganizationLocationAppServiceImpl.java`)
|
||||||
|
|
||||||
|
**变更内容**:
|
||||||
|
```diff
|
||||||
|
-organizationLocationService.getOrgLocListByActivityDefinitionId(orgLoc.getActivityDefinitionId());
|
||||||
|
+organizationLocationService.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getOrganizationId(),
|
||||||
|
+ orgLoc.getActivityDefinitionId());
|
||||||
|
```
|
||||||
|
|
||||||
|
编译验证通过。
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package com.core.framework.config;
|
package com.core.framework.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
@@ -8,6 +11,7 @@ import org.springframework.context.annotation.Bean;
|
|||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
@@ -23,6 +27,36 @@ import java.util.TimeZone;
|
|||||||
// 指定要扫描的Mapper类的包的路径
|
// 指定要扫描的Mapper类的包的路径
|
||||||
@MapperScan({"com.core.**.mapper", "com.openhis.**.mapper"})
|
@MapperScan({"com.core.**.mapper", "com.openhis.**.mapper"})
|
||||||
public class ApplicationConfig {
|
public class ApplicationConfig {
|
||||||
|
|
||||||
|
/** 支持多种日期格式的反序列化器 */
|
||||||
|
private static final JsonDeserializer<LocalDateTime> LOCAL_DATE_TIME_DESERIALIZER = new JsonDeserializer<LocalDateTime>() {
|
||||||
|
private static final DateTimeFormatter ISO_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||||
|
private static final DateTimeFormatter SIMPLE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
private static final DateTimeFormatter SLASH_FORMATTER = DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||||
|
String text = p.getText();
|
||||||
|
if (text == null || text.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 去除时区后缀 Z/z 和偏移量 +HH:MM/+HHMM(LocalDateTime 不含时区信息)
|
||||||
|
String cleaned = text.replaceAll("[Zz]$", "").replaceAll("[+-]\\d{2}:?\\d{2}$", "");
|
||||||
|
// 尝试 ISO 8601 格式(yyyy-MM-ddTHH:mm:ss.SSS)
|
||||||
|
try {
|
||||||
|
return LocalDateTime.parse(cleaned, ISO_FORMATTER);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
// 尝试简单格式(yyyy-MM-dd HH:mm:ss)
|
||||||
|
try {
|
||||||
|
return LocalDateTime.parse(cleaned, SIMPLE_FORMATTER);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
// 尝试斜杠格式(yyyy/M/d HH:mm:ss)
|
||||||
|
return LocalDateTime.parse(cleaned, SLASH_FORMATTER);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 时区配置
|
* 时区配置
|
||||||
*/
|
*/
|
||||||
@@ -35,7 +69,7 @@ public class ApplicationConfig {
|
|||||||
builder.simpleDateFormat("yyyy/M/d HH:mm:ss");
|
builder.simpleDateFormat("yyyy/M/d HH:mm:ss");
|
||||||
// 添加JavaTimeModule支持,用于LocalDateTime
|
// 添加JavaTimeModule支持,用于LocalDateTime
|
||||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
||||||
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
|
javaTimeModule.addDeserializer(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER);
|
||||||
builder.modules(javaTimeModule);
|
builder.modules(javaTimeModule);
|
||||||
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss")));
|
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss")));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -158,8 +158,10 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation
|
|||||||
? activityDefinitionMapper.selectById(activityDefinitionId) : null;
|
? activityDefinitionMapper.selectById(activityDefinitionId) : null;
|
||||||
String activityName = activityDef != null ? activityDef.getName() : "";
|
String activityName = activityDef != null ? activityDef.getName() : "";
|
||||||
|
|
||||||
|
// Only check for time conflicts within the same department
|
||||||
List<OrganizationLocation> organizationLocationList =
|
List<OrganizationLocation> organizationLocationList =
|
||||||
organizationLocationService.getOrgLocListByActivityDefinitionId(orgLoc.getActivityDefinitionId());
|
organizationLocationService.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getOrganizationId(),
|
||||||
|
orgLoc.getActivityDefinitionId());
|
||||||
organizationLocationList = (orgLoc.getId() != null)
|
organizationLocationList = (orgLoc.getId() != null)
|
||||||
? organizationLocationList.stream().filter(item -> !orgLoc.getId().equals(item.getId())).toList()
|
? organizationLocationList.stream().filter(item -> !orgLoc.getId().equals(item.getId())).toList()
|
||||||
: organizationLocationList;
|
: organizationLocationList;
|
||||||
@@ -169,11 +171,9 @@ public class OrganizationLocationAppServiceImpl implements IOrganizationLocation
|
|||||||
if (DateTimeUtils.isOverlap(organizationLocation.getStartTime(), organizationLocation.getEndTime(),
|
if (DateTimeUtils.isOverlap(organizationLocation.getStartTime(), organizationLocation.getEndTime(),
|
||||||
orgLoc.getStartTime(), orgLoc.getEndTime())) {
|
orgLoc.getStartTime(), orgLoc.getEndTime())) {
|
||||||
Organization org = organizationService.getById(organizationLocation.getOrganizationId());
|
Organization org = organizationService.getById(organizationLocation.getOrganizationId());
|
||||||
if (org == null) {
|
String organizationName = org != null ? org.getName() : ("科室[" + organizationLocation.getOrganizationId() + "]已删除");
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime()
|
return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime()
|
||||||
+ CommonConstants.Common.DASH + orgLoc.getEndTime() + "与" + org.getName() + "时间冲突");
|
+ CommonConstants.Common.DASH + orgLoc.getEndTime() + "与" + organizationName + "时间冲突");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (orgLocQueryDto.getId() != null) {
|
if (orgLocQueryDto.getId() != null) {
|
||||||
|
|||||||
@@ -215,6 +215,9 @@ public class SurgicalScheduleAppServiceImpl implements ISurgicalScheduleAppServi
|
|||||||
if (surgery != null) {
|
if (surgery != null) {
|
||||||
surgery.setStatusEnum(1); // 1 = 已排期
|
surgery.setStatusEnum(1); // 1 = 已排期
|
||||||
surgery.setUpdateTime(new Date());
|
surgery.setUpdateTime(new Date());
|
||||||
|
// Bug #558: 手术安排时同步写入手术室确认时间和确认人
|
||||||
|
surgery.setOperatingRoomConfirmTime(new Date());
|
||||||
|
surgery.setOperatingRoomConfirmUser(loginUser.getUsername());
|
||||||
|
|
||||||
// 填充缺失的申请科室和主刀医生名称
|
// 填充缺失的申请科室和主刀医生名称
|
||||||
fillSurgeryMissingNames(surgery);
|
fillSurgeryMissingNames(surgery);
|
||||||
|
|||||||
@@ -36,4 +36,7 @@ public class PerformInfoDto {
|
|||||||
/** 分组id */
|
/** 分组id */
|
||||||
@JsonSerialize(using = ToStringSerializer.class)
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
private Long groupId;
|
private Long groupId;
|
||||||
|
|
||||||
|
/** 退回原因 */
|
||||||
|
private String backReason;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2286,7 +2286,7 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
log.info("BugFix: signOffAdvice - 签退所有请求,状态改为待签发, requestIdList={}", requestIdList);
|
log.info("BugFix: signOffAdvice - 签退所有请求,状态改为待签发, requestIdList={}", requestIdList);
|
||||||
|
|
||||||
// 尝试签退药品请求(只有存在的才会更新)
|
// 尝试签退药品请求(只有存在的才会更新)
|
||||||
iMedicationRequestService.updateDraftStatusBatch(requestIdList, null, null);
|
iMedicationRequestService.updateDraftStatusBatch(requestIdList, null, null, null);
|
||||||
// 尝试签退耗材请求(只有存在的才会更新)
|
// 尝试签退耗材请求(只有存在的才会更新)
|
||||||
iDeviceRequestService.updateDraftStatusBatch(requestIdList);
|
iDeviceRequestService.updateDraftStatusBatch(requestIdList);
|
||||||
// 尝试签退诊疗请求(只有存在的才会更新)
|
// 尝试签退诊疗请求(只有存在的才会更新)
|
||||||
@@ -2343,21 +2343,52 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
|
|||||||
.map(UpdateGroupDto::getRequestId).collect(Collectors.toList());
|
.map(UpdateGroupDto::getRequestId).collect(Collectors.toList());
|
||||||
|
|
||||||
if (!idsToSetNull.isEmpty()) {
|
if (!idsToSetNull.isEmpty()) {
|
||||||
// 创建更新条件
|
// 对三个表都执行 group_id/group_no 置空(哪个表有该 id 就更新哪个)
|
||||||
UpdateWrapper<MedicationRequest> updateWrapper = new UpdateWrapper<>();
|
UpdateWrapper<MedicationRequest> medUpdateWrapper = new UpdateWrapper<>();
|
||||||
updateWrapper.set("group_id", null).in("id", idsToSetNull);
|
medUpdateWrapper.set("group_id", null).in("id", idsToSetNull);
|
||||||
|
iMedicationRequestService.update(medUpdateWrapper);
|
||||||
|
|
||||||
// 执行更新
|
UpdateWrapper<ServiceRequest> srvUpdateWrapper = new UpdateWrapper<>();
|
||||||
iMedicationRequestService.update(updateWrapper);
|
srvUpdateWrapper.set("group_id", null).in("id", idsToSetNull);
|
||||||
|
iServiceRequestService.update(srvUpdateWrapper);
|
||||||
|
|
||||||
|
// DeviceRequest 使用 group_no(String 类型)
|
||||||
|
UpdateWrapper<DeviceRequest> devUpdateWrapper = new UpdateWrapper<>();
|
||||||
|
devUpdateWrapper.set("group_no", null).in("id", idsToSetNull);
|
||||||
|
iDeviceRequestService.update(devUpdateWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理非null的情况
|
// 处理 groupId 非 null 的情况:按实际所属表分别更新
|
||||||
List<MedicationRequest> medicationRequestList = groupList.stream().filter(dto -> dto.getGroupId() != null)
|
List<UpdateGroupDto> nonNullGroupList = groupList.stream()
|
||||||
.map(dto -> new MedicationRequest().setId(dto.getRequestId()).setGroupId(dto.getGroupId()))
|
.filter(dto -> dto.getGroupId() != null).collect(Collectors.toList());
|
||||||
.collect(Collectors.toList());
|
if (!nonNullGroupList.isEmpty()) {
|
||||||
|
for (UpdateGroupDto dto : nonNullGroupList) {
|
||||||
if (!medicationRequestList.isEmpty()) {
|
Long reqId = dto.getRequestId();
|
||||||
iMedicationRequestService.saveOrUpdateBatch(medicationRequestList);
|
Long grpId = dto.getGroupId();
|
||||||
|
// 先尝试药品表(med_medication_request → group_id)
|
||||||
|
MedicationRequest medReq = iMedicationRequestService.getById(reqId);
|
||||||
|
if (medReq != null) {
|
||||||
|
UpdateWrapper<MedicationRequest> uw = new UpdateWrapper<>();
|
||||||
|
uw.set("group_id", grpId).eq("id", reqId);
|
||||||
|
iMedicationRequestService.update(uw);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 再尝试诊疗表(wor_service_request → group_id)
|
||||||
|
ServiceRequest srvReq = iServiceRequestService.getById(reqId);
|
||||||
|
if (srvReq != null) {
|
||||||
|
UpdateWrapper<ServiceRequest> uw = new UpdateWrapper<>();
|
||||||
|
uw.set("group_id", grpId).eq("id", reqId);
|
||||||
|
iServiceRequestService.update(uw);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 最后尝试耗材表(wor_device_request → group_no, String 类型)
|
||||||
|
DeviceRequest devReq = iDeviceRequestService.getById(reqId);
|
||||||
|
if (devReq != null) {
|
||||||
|
UpdateWrapper<DeviceRequest> uw = new UpdateWrapper<>();
|
||||||
|
uw.set("group_no", grpId != null ? grpId.toString() : null).eq("id", reqId);
|
||||||
|
iDeviceRequestService.update(uw);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
|||||||
Emr emr = new Emr();
|
Emr emr = new Emr();
|
||||||
BeanUtils.copyProperties(patientEmrDto, emr);
|
BeanUtils.copyProperties(patientEmrDto, emr);
|
||||||
String contextStr = patientEmrDto.getContextJson().toString();
|
String contextStr = patientEmrDto.getContextJson().toString();
|
||||||
Emr patientEmr = emrService.getOne(new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, emr.getEncounterId()));
|
Emr patientEmr = emrService.getOne(new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, emr.getEncounterId()).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false);
|
||||||
boolean saveSuccess;
|
boolean saveSuccess;
|
||||||
// 如果已经保存病历,再次保存走更新
|
// 如果已经保存病历,再次保存走更新
|
||||||
if (patientEmr != null) {
|
if (patientEmr != null) {
|
||||||
@@ -126,6 +126,10 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public R<?> getPatientEmrHistory(PatientEmrDto patientEmrDto, Integer pageNo, Integer pageSize) {
|
public R<?> getPatientEmrHistory(PatientEmrDto patientEmrDto, Integer pageNo, Integer pageSize) {
|
||||||
|
// 校验参数
|
||||||
|
if (patientEmrDto.getPatientId() == null) {
|
||||||
|
return R.ok(new Page<>(pageNo, pageSize));
|
||||||
|
}
|
||||||
Page<Emr> page = emrService.page(new Page<>(pageNo, pageSize),
|
Page<Emr> page = emrService.page(new Page<>(pageNo, pageSize),
|
||||||
new LambdaQueryWrapper<Emr>().eq(Emr::getPatientId, patientEmrDto.getPatientId()));
|
new LambdaQueryWrapper<Emr>().eq(Emr::getPatientId, patientEmrDto.getPatientId()));
|
||||||
return R.ok(page);
|
return R.ok(page);
|
||||||
@@ -140,8 +144,12 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public R<?> getEmrDetail(Long encounterId) {
|
public R<?> getEmrDetail(Long encounterId) {
|
||||||
|
// 校验参数
|
||||||
|
if (encounterId == null) {
|
||||||
|
return R.ok(null);
|
||||||
|
}
|
||||||
// 先查询门诊病历(emr表)
|
// 先查询门诊病历(emr表)
|
||||||
Emr emrDetail = emrService.getOne(new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounterId));
|
Emr emrDetail = emrService.getOne(new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounterId).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false);
|
||||||
if (emrDetail != null) {
|
if (emrDetail != null) {
|
||||||
return R.ok(emrDetail);
|
return R.ok(emrDetail);
|
||||||
}
|
}
|
||||||
@@ -151,7 +159,8 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
|||||||
new LambdaQueryWrapper<DocRecord>()
|
new LambdaQueryWrapper<DocRecord>()
|
||||||
.eq(DocRecord::getEncounterId, encounterId)
|
.eq(DocRecord::getEncounterId, encounterId)
|
||||||
.orderByDesc(DocRecord::getCreateTime)
|
.orderByDesc(DocRecord::getCreateTime)
|
||||||
.last("LIMIT 1")
|
.last("LIMIT 1"),
|
||||||
|
false
|
||||||
);
|
);
|
||||||
if (docRecord != null) {
|
if (docRecord != null) {
|
||||||
// 住院病历存在,也返回数据
|
// 住院病历存在,也返回数据
|
||||||
@@ -240,7 +249,7 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
|||||||
for (Encounter encounter : encounters) {
|
for (Encounter encounter : encounters) {
|
||||||
// 检查该就诊记录是否已经有病历
|
// 检查该就诊记录是否已经有病历
|
||||||
Emr existingEmr = emrService.getOne(
|
Emr existingEmr = emrService.getOne(
|
||||||
new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounter.getId())
|
new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounter.getId()).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false
|
||||||
);
|
);
|
||||||
|
|
||||||
// 检查该就诊是否由指定医生负责
|
// 检查该就诊是否由指定医生负责
|
||||||
@@ -298,7 +307,7 @@ public class DoctorStationEmrAppServiceImpl implements IDoctorStationEmrAppServi
|
|||||||
public R<?> checkNeedWriteEmr(Long encounterId) {
|
public R<?> checkNeedWriteEmr(Long encounterId) {
|
||||||
// 检查该就诊记录是否已经有病历
|
// 检查该就诊记录是否已经有病历
|
||||||
Emr existingEmr = emrService.getOne(
|
Emr existingEmr = emrService.getOne(
|
||||||
new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounterId)
|
new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounterId).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false
|
||||||
);
|
);
|
||||||
|
|
||||||
// 如果没有病历,则需要写病历
|
// 如果没有病历,则需要写病历
|
||||||
|
|||||||
@@ -121,6 +121,11 @@ public class RequestBaseDto {
|
|||||||
* 请求状态
|
* 请求状态
|
||||||
*/
|
*/
|
||||||
private Integer statusEnum;
|
private Integer statusEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 退回原因
|
||||||
|
*/
|
||||||
|
private String reasonText;
|
||||||
private String statusEnum_enumText;
|
private String statusEnum_enumText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ import java.time.ZoneId;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.format.DateTimeParseException;
|
import java.time.format.DateTimeParseException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,9 +234,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 手动处理前端传来的执行条件
|
// 为所有医嘱计算执行记录状态(所有页签都需要展示执行进度)
|
||||||
if (exeStatus != null) {
|
|
||||||
// 处理执行记录状态
|
|
||||||
for (InpatientAdviceDto inpatientAdvice : inpatientAdviceList) {
|
for (InpatientAdviceDto inpatientAdvice : inpatientAdviceList) {
|
||||||
List<PerformRecordDto> performRecordList = procedureRecordGroup.get(inpatientAdvice.getRequestId());
|
List<PerformRecordDto> performRecordList = procedureRecordGroup.get(inpatientAdvice.getRequestId());
|
||||||
List<PerformRecordDto> exePerformRecordList = new ArrayList<>();
|
List<PerformRecordDto> exePerformRecordList = new ArrayList<>();
|
||||||
@@ -262,8 +262,20 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
|||||||
inpatientAdvice.setExePerformRecordList(exePerformRecordList)
|
inpatientAdvice.setExePerformRecordList(exePerformRecordList)
|
||||||
.setCancelPerformRecordList(cancelPerformRecordList)
|
.setCancelPerformRecordList(cancelPerformRecordList)
|
||||||
.setStopPerformRecordList(stopPerformRecordList);
|
.setStopPerformRecordList(stopPerformRecordList);
|
||||||
|
// 计算综合执行状态文本
|
||||||
|
if (!exePerformRecordList.isEmpty()) {
|
||||||
|
inpatientAdvice.setOverallStatusText("已执行");
|
||||||
|
} else if (!cancelPerformRecordList.isEmpty()) {
|
||||||
|
inpatientAdvice.setOverallStatusText("已取消执行");
|
||||||
|
} else if (!stopPerformRecordList.isEmpty()) {
|
||||||
|
inpatientAdvice.setOverallStatusText("已停止");
|
||||||
|
} else {
|
||||||
|
inpatientAdvice.setOverallStatusText(inpatientAdvice.getRequestStatus_enumText());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 手动处理前端传来的执行条件
|
||||||
|
if (exeStatus != null) {
|
||||||
// 根据执行状态过滤医嘱列表
|
// 根据执行状态过滤医嘱列表
|
||||||
List<InpatientAdviceDto> filteredList = new ArrayList<>();
|
List<InpatientAdviceDto> filteredList = new ArrayList<>();
|
||||||
if (EventStatus.COMPLETED.getValue().equals(exeStatus)) {
|
if (EventStatus.COMPLETED.getValue().equals(exeStatus)) {
|
||||||
@@ -359,6 +371,29 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
|||||||
medRequestList.add(item);
|
medRequestList.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 校验医嘱是否已执行,已执行的医嘱不允许退回
|
||||||
|
List<PerformInfoDto> allRequestList = new ArrayList<>();
|
||||||
|
allRequestList.addAll(serviceRequestList);
|
||||||
|
allRequestList.addAll(medRequestList);
|
||||||
|
if (!allRequestList.isEmpty()) {
|
||||||
|
// 按requestTable分组查询执行记录
|
||||||
|
Map<String, List<Long>> requestTableIdMap = allRequestList.stream()
|
||||||
|
.collect(Collectors.groupingBy(PerformInfoDto::getRequestTable,
|
||||||
|
Collectors.mapping(PerformInfoDto::getRequestId, Collectors.toList())));
|
||||||
|
for (Map.Entry<String, List<Long>> entry : requestTableIdMap.entrySet()) {
|
||||||
|
String requestTable = entry.getKey();
|
||||||
|
List<Long> requestIds = entry.getValue();
|
||||||
|
List<Procedure> executedProcedures = procedureService.list(
|
||||||
|
new LambdaQueryWrapper<Procedure>()
|
||||||
|
.in(Procedure::getRequestId, requestIds)
|
||||||
|
.eq(Procedure::getRequestTable, requestTable)
|
||||||
|
.eq(Procedure::getStatusEnum, EventStatus.COMPLETED.getValue())
|
||||||
|
.eq(Procedure::getCategoryEnum, ProcedureCategory.INPATIENT_ADVICE.getValue()));
|
||||||
|
if (!executedProcedures.isEmpty()) {
|
||||||
|
return R.fail("所选医嘱中存在已执行的医嘱,请先在【医嘱执行】界面取消执行后再退回");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// 校验药品医嘱是否已发药,已发药的医嘱不允许退回
|
// 校验药品医嘱是否已发药,已发药的医嘱不允许退回
|
||||||
if (!medRequestList.isEmpty()) {
|
if (!medRequestList.isEmpty()) {
|
||||||
List<Long> medReqIds = medRequestList.stream().map(PerformInfoDto::getRequestId).toList();
|
List<Long> medReqIds = medRequestList.stream().map(PerformInfoDto::getRequestId).toList();
|
||||||
@@ -372,15 +407,21 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
|||||||
}
|
}
|
||||||
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
|
||||||
Date checkDate = new Date();
|
Date checkDate = new Date();
|
||||||
|
// 从请求中提取退回原因(所有项目共享同一原因)
|
||||||
|
String backReason = performInfoList.stream()
|
||||||
|
.map(PerformInfoDto::getBackReason)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(null);
|
||||||
if (!serviceRequestList.isEmpty()) {
|
if (!serviceRequestList.isEmpty()) {
|
||||||
// 更新服务请求状态待发送
|
// 更新服务请求状态待发送
|
||||||
serviceRequestService.updateDraftStatus(
|
serviceRequestService.updateDraftStatus(
|
||||||
serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
|
serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason);
|
||||||
}
|
}
|
||||||
if (!medRequestList.isEmpty()) {
|
if (!medRequestList.isEmpty()) {
|
||||||
// 更新药品请求状态待发送
|
// 更新药品请求状态待发送
|
||||||
medicationRequestService.updateDraftStatusBatch(
|
medicationRequestService.updateDraftStatusBatch(
|
||||||
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
|
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason);
|
||||||
}
|
}
|
||||||
return R.ok(null, "退回成功");
|
return R.ok(null, "退回成功");
|
||||||
}
|
}
|
||||||
@@ -524,7 +565,10 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
|
|||||||
// 处理长期已发放的药品
|
// 处理长期已发放的药品
|
||||||
if (!longMedDispensedList.isEmpty()) {
|
if (!longMedDispensedList.isEmpty()) {
|
||||||
// 生成退药单
|
// 生成退药单
|
||||||
this.creatRefundMedicationList(tempMedDispensedList, procedureIdMap);
|
this.creatRefundMedicationList(longMedDispensedList, procedureIdMap);
|
||||||
|
// 药品退药请求状态变更(待退药)
|
||||||
|
medicationRequestService.updateCancelledStatusBatch(
|
||||||
|
longMedDispensedList.stream().map(MedicationDispense::getMedReqId).toList(), null, null);
|
||||||
}
|
}
|
||||||
// 处理临时已发放药品
|
// 处理临时已发放药品
|
||||||
if (!tempMedDispensedList.isEmpty()) {
|
if (!tempMedDispensedList.isEmpty()) {
|
||||||
|
|||||||
@@ -101,6 +101,9 @@ public class InpatientAdviceDto {
|
|||||||
private Integer requestStatus;
|
private Integer requestStatus;
|
||||||
private String requestStatus_enumText;
|
private String requestStatus_enumText;
|
||||||
|
|
||||||
|
/** 综合执行状态(结合请求状态和执行记录计算) */
|
||||||
|
private String overallStatusText;
|
||||||
|
|
||||||
/** 是否皮试 */
|
/** 是否皮试 */
|
||||||
private Integer skinTestFlag;
|
private Integer skinTestFlag;
|
||||||
private String skinTestFlag_enumText;
|
private String skinTestFlag_enumText;
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ public class OutpatientInfusionAppServiceImpl implements IOutpatientInfusionAppS
|
|||||||
}
|
}
|
||||||
boolean result = serviceRequestService.updateCancelledStatus(serviceReqId, now, practitionerId, orgId);
|
boolean result = serviceRequestService.updateCancelledStatus(serviceReqId, now, practitionerId, orgId);
|
||||||
// 更新主服务请求状态为待执行
|
// 更新主服务请求状态为待执行
|
||||||
serviceRequestService.updateDraftStatus(List.of(serviceRequest.getBasedOnId()), null, null);
|
serviceRequestService.updateDraftStatus(List.of(serviceRequest.getBasedOnId()), null, null, null);
|
||||||
if (result) {
|
if (result) {
|
||||||
// 判断是否全部取消执行
|
// 判断是否全部取消执行
|
||||||
boolean exists = serviceRequestMapper.exists(new LambdaQueryWrapper<ServiceRequest>()
|
boolean exists = serviceRequestMapper.exists(new LambdaQueryWrapper<ServiceRequest>()
|
||||||
|
|||||||
@@ -627,7 +627,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
|||||||
longServiceRequest.setPatientId(regAdviceSaveDto.getPatientId()); // 患者
|
longServiceRequest.setPatientId(regAdviceSaveDto.getPatientId()); // 患者
|
||||||
longServiceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
|
longServiceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
|
||||||
longServiceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
|
longServiceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
|
||||||
longServiceRequest.setOrgId(regAdviceSaveDto.getPositionId()); // 执行科室
|
longServiceRequest.setOrgId(regAdviceSaveDto.getEffectiveOrgId()); // 执行科室
|
||||||
longServiceRequest.setContentJson(regAdviceSaveDto.getContentJson()); // 请求内容json
|
longServiceRequest.setContentJson(regAdviceSaveDto.getContentJson()); // 请求内容json
|
||||||
longServiceRequest.setYbClassEnum(regAdviceSaveDto.getYbClassEnum());// 类别医保编码
|
longServiceRequest.setYbClassEnum(regAdviceSaveDto.getYbClassEnum());// 类别医保编码
|
||||||
longServiceRequest.setConditionId(regAdviceSaveDto.getConditionId()); // 诊断id
|
longServiceRequest.setConditionId(regAdviceSaveDto.getConditionId()); // 诊断id
|
||||||
@@ -678,7 +678,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
|||||||
tempServiceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
|
tempServiceRequest.setRequesterId(regAdviceSaveDto.getPractitionerId()); // 开方医生
|
||||||
tempServiceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
|
tempServiceRequest.setEncounterId(regAdviceSaveDto.getEncounterId()); // 就诊id
|
||||||
tempServiceRequest.setAuthoredTime(curDate); // 请求签发时间
|
tempServiceRequest.setAuthoredTime(curDate); // 请求签发时间
|
||||||
tempServiceRequest.setOrgId(regAdviceSaveDto.getPositionId()); // 执行科室
|
tempServiceRequest.setOrgId(regAdviceSaveDto.getEffectiveOrgId()); // 执行科室
|
||||||
tempServiceRequest.setContentJson(regAdviceSaveDto.getContentJson()); // 请求内容json
|
tempServiceRequest.setContentJson(regAdviceSaveDto.getContentJson()); // 请求内容json
|
||||||
tempServiceRequest.setYbClassEnum(regAdviceSaveDto.getYbClassEnum());// 类别医保编码
|
tempServiceRequest.setYbClassEnum(regAdviceSaveDto.getYbClassEnum());// 类别医保编码
|
||||||
tempServiceRequest.setConditionId(regAdviceSaveDto.getConditionId()); // 诊断id
|
tempServiceRequest.setConditionId(regAdviceSaveDto.getConditionId()); // 诊断id
|
||||||
@@ -1016,7 +1016,7 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
|
|||||||
}
|
}
|
||||||
if (!medicineRequestIds.isEmpty()) {
|
if (!medicineRequestIds.isEmpty()) {
|
||||||
// 根据请求id更新请求状态
|
// 根据请求id更新请求状态
|
||||||
iMedicationRequestService.updateDraftStatusBatch(medicineRequestIds, null, null);
|
iMedicationRequestService.updateDraftStatusBatch(medicineRequestIds, null, null, null);
|
||||||
}
|
}
|
||||||
if (!activityRequestIds.isEmpty()) {
|
if (!activityRequestIds.isEmpty()) {
|
||||||
// 根据请求id更新请求状态
|
// 根据请求id更新请求状态
|
||||||
|
|||||||
@@ -10,8 +10,4 @@ import lombok.experimental.Accessors;
|
|||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class RegAdviceSaveDto extends AdviceSaveDto {
|
public class RegAdviceSaveDto extends AdviceSaveDto {
|
||||||
|
|
||||||
/** 请求类型 */
|
|
||||||
private Integer categoryEnum;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -516,6 +516,7 @@
|
|||||||
T1.patient_id AS patient_id,
|
T1.patient_id AS patient_id,
|
||||||
'med_medication_definition' AS advice_table_name,
|
'med_medication_definition' AS advice_table_name,
|
||||||
T1.medication_id AS advice_definition_id
|
T1.medication_id AS advice_definition_id
|
||||||
|
, T1.back_reason AS reason_text
|
||||||
FROM med_medication_request AS T1
|
FROM med_medication_request AS T1
|
||||||
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
|
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
|
||||||
AND T2.delete_flag = '0'
|
AND T2.delete_flag = '0'
|
||||||
@@ -577,6 +578,7 @@
|
|||||||
T1.patient_id AS patient_id,
|
T1.patient_id AS patient_id,
|
||||||
'med_medication_definition' AS advice_table_name,
|
'med_medication_definition' AS advice_table_name,
|
||||||
T3.ID AS advice_definition_id
|
T3.ID AS advice_definition_id
|
||||||
|
, T2.back_reason AS reason_text
|
||||||
FROM adm_charge_item AS T1
|
FROM adm_charge_item AS T1
|
||||||
INNER JOIN med_medication_request AS T2 ON T2.ID = T1.service_id AND T2.delete_flag = '0'
|
INNER JOIN med_medication_request AS T2 ON T2.ID = T1.service_id AND T2.delete_flag = '0'
|
||||||
LEFT JOIN med_medication_definition AS T3 ON T3.ID = T2.medication_id AND T3.delete_flag = '0'
|
LEFT JOIN med_medication_definition AS T3 ON T3.ID = T2.medication_id AND T3.delete_flag = '0'
|
||||||
@@ -637,6 +639,7 @@
|
|||||||
CI.patient_id AS patient_id,
|
CI.patient_id AS patient_id,
|
||||||
'adm_device_definition' AS advice_table_name,
|
'adm_device_definition' AS advice_table_name,
|
||||||
CI.product_id AS advice_definition_id
|
CI.product_id AS advice_definition_id
|
||||||
|
, NULL AS reason_text
|
||||||
FROM adm_charge_item AS CI
|
FROM adm_charge_item AS CI
|
||||||
LEFT JOIN adm_charge_item_definition CID ON CID.id = CI.definition_id AND CID.delete_flag = '0'
|
LEFT JOIN adm_charge_item_definition CID ON CID.id = CI.definition_id AND CID.delete_flag = '0'
|
||||||
LEFT JOIN wor_device_request DR ON DR.id = CI.service_id AND DR.delete_flag = '0'
|
LEFT JOIN wor_device_request DR ON DR.id = CI.service_id AND DR.delete_flag = '0'
|
||||||
@@ -691,6 +694,7 @@
|
|||||||
T1.patient_id AS patient_id,
|
T1.patient_id AS patient_id,
|
||||||
'adm_device_definition' AS advice_table_name,
|
'adm_device_definition' AS advice_table_name,
|
||||||
T1.device_def_id AS advice_definition_id
|
T1.device_def_id AS advice_definition_id
|
||||||
|
, NULL AS reason_text
|
||||||
FROM wor_device_request AS T1
|
FROM wor_device_request AS T1
|
||||||
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
|
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
|
||||||
AND T2.delete_flag = '0'
|
AND T2.delete_flag = '0'
|
||||||
@@ -747,6 +751,7 @@
|
|||||||
T1.patient_id AS patient_id,
|
T1.patient_id AS patient_id,
|
||||||
'wor_activity_definition' AS advice_table_name,
|
'wor_activity_definition' AS advice_table_name,
|
||||||
T1.activity_id AS advice_definition_id
|
T1.activity_id AS advice_definition_id
|
||||||
|
, T1.reason_text AS reason_text
|
||||||
FROM wor_service_request AS T1
|
FROM wor_service_request AS T1
|
||||||
LEFT JOIN wor_activity_definition AS T2
|
LEFT JOIN wor_activity_definition AS T2
|
||||||
ON T2.ID = T1.activity_id
|
ON T2.ID = T1.activity_id
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.openhis.lab.domain;
|
package com.openhis.lab.domain;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
@@ -106,10 +107,12 @@ public class InspectionPackage {
|
|||||||
|
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
/** 更新时间 */
|
/** 更新时间 */
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
/** 删除标志(false-正常,true-删除) */
|
/** 删除标志(false-正常,true-删除) */
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.openhis.lab.domain;
|
package com.openhis.lab.domain;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
@@ -75,10 +76,12 @@ public class InspectionPackageDetail {
|
|||||||
|
|
||||||
/** 创建时间 */
|
/** 创建时间 */
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
/** 更新时间 */
|
/** 更新时间 */
|
||||||
@TableField("update_time")
|
@TableField("update_time")
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||||
private LocalDateTime updateTime;
|
private LocalDateTime updateTime;
|
||||||
|
|
||||||
/** 删除标志(false-正常,true-删除) */
|
/** 删除标志(false-正常,true-删除) */
|
||||||
|
|||||||
@@ -111,6 +111,9 @@ public class MedicationRequest extends HisBaseEntity {
|
|||||||
/** 支持用药信息 */
|
/** 支持用药信息 */
|
||||||
private String supportInfo;
|
private String supportInfo;
|
||||||
|
|
||||||
|
/** 退回原因 */
|
||||||
|
private String backReason;
|
||||||
|
|
||||||
/** 请求开始时间 */
|
/** 请求开始时间 */
|
||||||
private Date reqAuthoredTime;
|
private Date reqAuthoredTime;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public interface IMedicationRequestService extends IService<MedicationRequest> {
|
|||||||
* @param practitionerId 校对人
|
* @param practitionerId 校对人
|
||||||
* @param checkDate 校对时间
|
* @param checkDate 校对时间
|
||||||
*/
|
*/
|
||||||
void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate);
|
void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate, String backReason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新请求状态:取消
|
* 更新请求状态:取消
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public class MedicationRequestServiceImpl extends ServiceImpl<MedicationRequestM
|
|||||||
* @param checkDate 校对时间
|
* @param checkDate 校对时间
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate) {
|
public void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate, String backReason) {
|
||||||
LambdaUpdateWrapper<MedicationRequest> updateWrapper =
|
LambdaUpdateWrapper<MedicationRequest> updateWrapper =
|
||||||
new LambdaUpdateWrapper<MedicationRequest>().in(MedicationRequest::getId, requestIdList)
|
new LambdaUpdateWrapper<MedicationRequest>().in(MedicationRequest::getId, requestIdList)
|
||||||
.set(MedicationRequest::getStatusEnum, RequestStatus.DRAFT.getValue());
|
.set(MedicationRequest::getStatusEnum, RequestStatus.DRAFT.getValue());
|
||||||
@@ -54,6 +54,9 @@ public class MedicationRequestServiceImpl extends ServiceImpl<MedicationRequestM
|
|||||||
if (checkDate != null) {
|
if (checkDate != null) {
|
||||||
updateWrapper.set(MedicationRequest::getCheckTime, checkDate);
|
updateWrapper.set(MedicationRequest::getCheckTime, checkDate);
|
||||||
}
|
}
|
||||||
|
if (backReason != null) {
|
||||||
|
updateWrapper.set(MedicationRequest::getBackReason, backReason);
|
||||||
|
}
|
||||||
baseMapper.update(null, updateWrapper);
|
baseMapper.update(null, updateWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public interface IServiceRequestService extends IService<ServiceRequest> {
|
|||||||
* @param practitionerId 校对人
|
* @param practitionerId 校对人
|
||||||
* @param checkDate 校对时间
|
* @param checkDate 校对时间
|
||||||
*/
|
*/
|
||||||
void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate);
|
void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate, String backReason);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新服务状态:待发送
|
* 更新服务状态:待发送
|
||||||
|
|||||||
@@ -172,9 +172,15 @@ public class ServiceRequestServiceImpl extends ServiceImpl<ServiceRequestMapper,
|
|||||||
* @param checkDate 校对时间
|
* @param checkDate 校对时间
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate) {
|
public void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate, String backReason) {
|
||||||
baseMapper.update(new ServiceRequest().setStatusEnum(RequestStatus.DRAFT.getValue())
|
ServiceRequest updateEntity = new ServiceRequest()
|
||||||
.setPerformerCheckId(SecurityUtils.getLoginUser().getPractitionerId()).setCheckTime(DateUtils.getNowDate()),
|
.setStatusEnum(RequestStatus.DRAFT.getValue())
|
||||||
|
.setPerformerCheckId(SecurityUtils.getLoginUser().getPractitionerId())
|
||||||
|
.setCheckTime(DateUtils.getNowDate());
|
||||||
|
if (backReason != null && !backReason.isEmpty()) {
|
||||||
|
updateEntity.setReasonText(backReason);
|
||||||
|
}
|
||||||
|
baseMapper.update(updateEntity,
|
||||||
new LambdaUpdateWrapper<ServiceRequest>().in(ServiceRequest::getId, serviceRequestIdList)
|
new LambdaUpdateWrapper<ServiceRequest>().in(ServiceRequest::getId, serviceRequestIdList)
|
||||||
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
|
.eq(ServiceRequest::getDeleteFlag, DelFlag.NO.getCode()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
-- Bug #613: 医嘱退回流程 — med_medication_request 表缺少退回原因字段
|
||||||
|
-- 执行前检查:如果列已存在则跳过
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM information_schema.columns
|
||||||
|
WHERE table_name = 'med_medication_request' AND column_name = 'back_reason'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE med_medication_request ADD COLUMN back_reason VARCHAR(500) DEFAULT NULL;
|
||||||
|
COMMENT ON COLUMN med_medication_request.back_reason IS '退回原因';
|
||||||
|
END IF;
|
||||||
|
END
|
||||||
|
$$;
|
||||||
@@ -1190,7 +1190,7 @@ const loadCategoryItems = async (categoryKey, loadMore = false) => {
|
|||||||
const mappedItems = records.map(item => {
|
const mappedItems = records.map(item => {
|
||||||
// 套餐项目处理:需同时满足 feePackageId 有效且 packageName 非空
|
// 套餐项目处理:需同时满足 feePackageId 有效且 packageName 非空
|
||||||
// BugFix#556: 增加 packageName 联合判断,避免普通项目因 feePackageId 有值被误标为套餐
|
// BugFix#556: 增加 packageName 联合判断,避免普通项目因 feePackageId 有值被误标为套餐
|
||||||
const isPackage = item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null' && item.packageName
|
const isPackage = Boolean(item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null' && item.packageName)
|
||||||
const itemPrice = isPackage
|
const itemPrice = isPackage
|
||||||
? (parseFloat(item.packageAmount || 0) || parseFloat(item.retailPrice || 0) || parseFloat(item.price || 0))
|
? (parseFloat(item.packageAmount || 0) || parseFloat(item.retailPrice || 0) || parseFloat(item.price || 0))
|
||||||
: (parseFloat(item.retailPrice || 0) || parseFloat(item.price || 0))
|
: (parseFloat(item.retailPrice || 0) || parseFloat(item.price || 0))
|
||||||
@@ -1678,7 +1678,7 @@ const handleSave = () => {
|
|||||||
// Bug #326修复: 传入 activityId,后端直接使用 ID 关联,避免用名称反查
|
// Bug #326修复: 传入 activityId,后端直接使用 ID 关联,避免用名称反查
|
||||||
activityId: item.activityId || item.itemId || null,
|
activityId: item.activityId || item.itemId || null,
|
||||||
feePackageId: item.feePackageId || null,
|
feePackageId: item.feePackageId || null,
|
||||||
isPackage: item.isPackage || false,
|
isPackage: Boolean(item.isPackage),
|
||||||
sampleType: item.sampleType || '',
|
sampleType: item.sampleType || '',
|
||||||
unit: item.unit || ''
|
unit: item.unit || ''
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -198,7 +198,7 @@
|
|||||||
v-model="scope.row.adviceName"
|
v-model="scope.row.adviceName"
|
||||||
placeholder="请选择项目"
|
placeholder="请选择项目"
|
||||||
@input="handleChange"
|
@input="handleChange"
|
||||||
@click="handleFocus(scope.row, scope.$index)"
|
@focus="handleFocus(scope.row, scope.$index)"
|
||||||
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
|
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
|
||||||
@keydown="
|
@keydown="
|
||||||
(e) => {
|
(e) => {
|
||||||
@@ -640,6 +640,10 @@ function getListInfo(addNewRow) {
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
|
// 没有 requestTime 的项(新增/组套添加)排在最前面
|
||||||
|
if (!a.requestTime && !b.requestTime) return 0;
|
||||||
|
if (!a.requestTime) return -1;
|
||||||
|
if (!b.requestTime) return 1;
|
||||||
return new Date(b.requestTime) - new Date(a.requestTime);
|
return new Date(b.requestTime) - new Date(a.requestTime);
|
||||||
});
|
});
|
||||||
getGroupMarkers(); // 更新标记
|
getGroupMarkers(); // 更新标记
|
||||||
@@ -896,31 +900,16 @@ function handleDiagnosisChange(item) {
|
|||||||
function handleFocus(row, index) {
|
function handleFocus(row, index) {
|
||||||
rowIndex.value = index;
|
rowIndex.value = index;
|
||||||
row.showPopover = true;
|
row.showPopover = true;
|
||||||
|
// Bug #555: handleFocus 只负责开 popover 和初始化查询参数,搜索由 handleChange 统一处理
|
||||||
|
// 避免异步 refresh 用旧闭包 searchKey 覆盖 handleChange 的搜索结果
|
||||||
const adviceType = row.adviceType !== undefined ? row.adviceType : adviceQueryParams.value.adviceType;
|
const adviceType = row.adviceType !== undefined ? row.adviceType : adviceQueryParams.value.adviceType;
|
||||||
// 用 adviceType + categoryCode 组合查找匹配的选项
|
let categoryCode = '';
|
||||||
|
if (row.adviceType !== undefined) {
|
||||||
const selectValue = (adviceType == 1 && row.categoryCode) ? '1-' + row.categoryCode : adviceType;
|
const selectValue = (adviceType == 1 && row.categoryCode) ? '1-' + row.categoryCode : adviceType;
|
||||||
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
|
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
|
||||||
// If the row has an explicit adviceType (saved/existing row), use its own categoryCode.
|
categoryCode = selectedItem ? selectedItem.categoryCode : (row.categoryCode || '');
|
||||||
// If no type is selected (new row), use empty string for global search across all categories.
|
|
||||||
const categoryCode = selectedItem ? selectedItem.categoryCode : (row.adviceType != null ? (row.categoryCode || '') : '');
|
|
||||||
const searchKey = row.adviceName || '';
|
|
||||||
|
|
||||||
nextTick(() => {
|
|
||||||
nextTick(() => {
|
|
||||||
const tableRef = Array.isArray(adviceTableRef.value) ? adviceTableRef.value[index] : adviceTableRef.value;
|
|
||||||
if (tableRef && tableRef.refresh) {
|
|
||||||
tableRef.refresh(adviceType, categoryCode, searchKey);
|
|
||||||
} else {
|
|
||||||
// fallback: 如果双重 nextTick 仍未挂载,延迟 100ms 再试
|
|
||||||
setTimeout(() => {
|
|
||||||
const tableRef2 = Array.isArray(adviceTableRef.value) ? adviceTableRef.value[index] : adviceTableRef.value;
|
|
||||||
if (tableRef2 && tableRef2.refresh) {
|
|
||||||
tableRef2.refresh(adviceType, categoryCode, searchKey);
|
|
||||||
}
|
}
|
||||||
}, 100);
|
adviceQueryParams.value = { adviceType, categoryCode, searchKey: '' };
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleBlur(row) {
|
function handleBlur(row) {
|
||||||
@@ -929,20 +918,24 @@ function handleBlur(row) {
|
|||||||
|
|
||||||
function handleChange(value) {
|
function handleChange(value) {
|
||||||
adviceQueryParams.value.searchKey = value;
|
adviceQueryParams.value.searchKey = value;
|
||||||
// 搜索词变化时,调用当前行子组件的 refresh 方法
|
// @focus 已先于 @input 执行,rowIndex 必定有效
|
||||||
const index = rowIndex.value;
|
const currentIndex = rowIndex.value;
|
||||||
if (index >= 0) {
|
if (currentIndex < 0) return;
|
||||||
const tableRef = Array.isArray(adviceTableRef.value) ? adviceTableRef.value[index] : adviceTableRef.value;
|
const row = filterPrescriptionList.value[currentIndex];
|
||||||
|
// popover 被 blur 关闭后,用户继续输入时自行打开
|
||||||
|
if (!row.showPopover) {
|
||||||
|
row.showPopover = true;
|
||||||
|
}
|
||||||
|
const tableRef = Array.isArray(adviceTableRef.value) ? adviceTableRef.value[currentIndex] : adviceTableRef.value;
|
||||||
if (tableRef && tableRef.refresh) {
|
if (tableRef && tableRef.refresh) {
|
||||||
const row = filterPrescriptionList.value[index];
|
|
||||||
const adviceType = row?.adviceType !== undefined ? row.adviceType : adviceQueryParams.value.adviceType;
|
const adviceType = row?.adviceType !== undefined ? row.adviceType : adviceQueryParams.value.adviceType;
|
||||||
// 用 adviceType + categoryCode 组合查找匹配的选项
|
let categoryCode = '';
|
||||||
|
if (row?.adviceType !== undefined) {
|
||||||
const selectValue = (adviceType == 1 && row?.categoryCode) ? '1-' + row.categoryCode : adviceType;
|
const selectValue = (adviceType == 1 && row?.categoryCode) ? '1-' + row.categoryCode : adviceType;
|
||||||
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
|
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
|
||||||
// 修复Bug #486:当行没有显式选择医嘱类型时,不传categoryCode,让搜索在全药库中进行
|
categoryCode = selectedItem ? selectedItem.categoryCode : (adviceQueryParams.value.categoryCode || '');
|
||||||
const categoryCode = selectedItem ? selectedItem.categoryCode : (row?.adviceType !== undefined ? (adviceQueryParams.value.categoryCode || '') : '');
|
|
||||||
tableRef.refresh(adviceType, categoryCode, value);
|
|
||||||
}
|
}
|
||||||
|
tableRef.refresh(adviceType, categoryCode, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1579,11 +1572,24 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
|
|
||||||
let successCount = 0;
|
let successCount = 0;
|
||||||
|
|
||||||
|
// 收集所有要添加的新行,最后统一 unshift 到数组开头(置顶显示)
|
||||||
|
const newRows = [];
|
||||||
|
|
||||||
|
// 记录循环前的数组长度,用于清理循环中创建的临时行
|
||||||
|
const originalLength = prescriptionList.value.length;
|
||||||
|
|
||||||
orderGroupList.forEach((item) => {
|
orderGroupList.forEach((item) => {
|
||||||
rowIndex.value = prescriptionList.value.length;
|
// 使用临时索引,先追加到末尾用于 setValue 填充
|
||||||
|
const tempIndex = prescriptionList.value.length;
|
||||||
|
prescriptionList.value[tempIndex] = {
|
||||||
|
uniqueKey: nextId.value++,
|
||||||
|
isEdit: false,
|
||||||
|
statusEnum: 1,
|
||||||
|
};
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
console.warn('组套中的项目为空');
|
console.warn('组套中的项目为空');
|
||||||
|
prescriptionList.value.splice(tempIndex, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,18 +1615,12 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
therapyEnum: item.orderDetailInfos?.therapyEnum || '1',
|
therapyEnum: item.orderDetailInfos?.therapyEnum || '1',
|
||||||
};
|
};
|
||||||
|
|
||||||
// 预初始化空行(组套项带预填值,设为 false 让明细字段在表格中直接展示)
|
rowIndex.value = tempIndex;
|
||||||
prescriptionList.value[rowIndex.value] = {
|
|
||||||
uniqueKey: nextId.value++,
|
|
||||||
isEdit: false,
|
|
||||||
statusEnum: 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
setValue(mergedDetail);
|
setValue(mergedDetail);
|
||||||
|
|
||||||
// 创建新的处方项目
|
// 创建新的处方项目
|
||||||
const newRow = {
|
const newRow = {
|
||||||
...prescriptionList.value[rowIndex.value],
|
...prescriptionList.value[tempIndex],
|
||||||
patientId: patientInfo.value.patientId,
|
patientId: patientInfo.value.patientId,
|
||||||
encounterId: patientInfo.value.encounterId,
|
encounterId: patientInfo.value.encounterId,
|
||||||
accountId: accountId.value,
|
accountId: accountId.value,
|
||||||
@@ -1639,12 +1639,12 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
orgId: resolveOrgId(mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '',
|
orgId: resolveOrgId(mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '',
|
||||||
// 🔧 修复:同时存储 orgName,确保树匹配不到时仍有中文名称可显示
|
// 🔧 修复:同时存储 orgName,确保树匹配不到时仍有中文名称可显示
|
||||||
orgName: findOrgName(mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || mergedDetail.orgName || patientInfo.value?.inHospitalOrgName || '',
|
orgName: findOrgName(mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || mergedDetail.orgName || patientInfo.value?.inHospitalOrgName || '',
|
||||||
dbOpType: prescriptionList.value[rowIndex.value].requestId ? '2' : '1',
|
dbOpType: prescriptionList.value[tempIndex].requestId ? '2' : '1',
|
||||||
conditionId: conditionId.value,
|
conditionId: conditionId.value,
|
||||||
conditionDefinitionId: conditionDefinitionId.value,
|
conditionDefinitionId: conditionDefinitionId.value,
|
||||||
encounterDiagnosisId: encounterDiagnosisId.value,
|
encounterDiagnosisId: encounterDiagnosisId.value,
|
||||||
diagnosisName: diagnosisName.value,
|
diagnosisName: diagnosisName.value,
|
||||||
therapyEnum: prescriptionList.value[rowIndex.value]?.therapyEnum || mergedDetail.therapyEnum || '1',
|
therapyEnum: prescriptionList.value[tempIndex]?.therapyEnum || mergedDetail.therapyEnum || '1',
|
||||||
// 🔧 修复:确保组套医嘱的 categoryEnum 被正确映射,防止后端 NPE
|
// 🔧 修复:确保组套医嘱的 categoryEnum 被正确映射,防止后端 NPE
|
||||||
categoryEnum: mergedDetail?.categoryEnum || mergedDetail?.categoryCode || item?.categoryCode,
|
categoryEnum: mergedDetail?.categoryEnum || mergedDetail?.categoryCode || item?.categoryCode,
|
||||||
};
|
};
|
||||||
@@ -1663,11 +1663,14 @@ function handleSaveGroup(orderGroupList) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newRow.contentJson = JSON.stringify(newRow);
|
newRow.contentJson = JSON.stringify(newRow);
|
||||||
prescriptionList.value[rowIndex.value] = newRow;
|
newRows.push(newRow);
|
||||||
successCount++;
|
successCount++;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (successCount > 0) {
|
// 清理循环中创建的临时行,统一添加到数组开头(置顶显示)
|
||||||
|
if (newRows.length > 0) {
|
||||||
|
prescriptionList.value.splice(originalLength); // 移除循环中追加到末尾的临时行
|
||||||
|
prescriptionList.value.unshift(...newRows);
|
||||||
proxy.$modal.msgSuccess(`成功添加 ${successCount} 个医嘱项`);
|
proxy.$modal.msgSuccess(`成功添加 ${successCount} 个医嘱项`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ function handleClick(tabName) {
|
|||||||
break;
|
break;
|
||||||
case 'cancel':
|
case 'cancel':
|
||||||
exeStatus.value = 9;
|
exeStatus.value = 9;
|
||||||
|
requestStatus.value = RequestStatus.CANCELLED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1818,11 +1818,14 @@ function handleQuoteBilling() {
|
|||||||
temporaryBillingMedicines.value = []
|
temporaryBillingMedicines.value = []
|
||||||
temporaryAdvices.value = []
|
temporaryAdvices.value = []
|
||||||
|
|
||||||
// 🔧 修复 Bug #445: 只保留药品类型(adviceType=1),过滤掉耗材(2)和诊疗项目(3/6)
|
// 🔧 修复 Bug #444: 统一过滤逻辑,与 handleMedicalAdvice 保持一致
|
||||||
// 同时过滤掉已有 requestId 的项目(已生成医嘱的不需要再次显示在"待生成"列表中)
|
// 1. 使用 Number() + snake_case 回退,避免类型转换导致过滤失效
|
||||||
// 先提取已签发项目(statusEnum=2)填充已生成列表
|
// 2. 增加关键词二次过滤,排除手术/检查/诊疗等非药品项目
|
||||||
const activeItems = res.data.filter(item => {
|
const filteredItems = res.data.filter(item => {
|
||||||
|
// 匹配 encounterId
|
||||||
if (item.encounterId !== temporaryPatientInfo.value.visitId) return false;
|
if (item.encounterId !== temporaryPatientInfo.value.visitId) return false;
|
||||||
|
// 只保留药品类型(adviceType=1),过滤掉耗材(2)和诊疗项目(3/6)
|
||||||
|
// 🔧 修复 Bug #444: 使用 Number() 显式转换,增加 snake_case 回退
|
||||||
const at = Number(item.adviceType ?? item.advice_type);
|
const at = Number(item.adviceType ?? item.advice_type);
|
||||||
if (at !== 1 && at !== 2) return false;
|
if (at !== 1 && at !== 2) return false;
|
||||||
if (item.statusEnum !== 2) return false;
|
if (item.statusEnum !== 2) return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user