Compare commits

..

8 Commits

Author SHA1 Message Date
Ranyunqiao
f84940fa5f 553 【住院护士站-医嘱校对】医嘱列表缺少“医嘱状态”显示列 2026-05-19 18:08:44 +08:00
e3db810972 Fix Bug #469: 根因+修复方案摘要 2026-05-19 18:08:44 +08:00
85e95420b7 Fix Bug #547: 执行科室配置保存时,冲突检测应跳过已被软删除科室的孤脏记录 — 根因:时间冲突校验未排除科室已删除的 OrganizationLocation 记录,导致已不存在的科室仍会阻断新配置保存
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 18:08:44 +08:00
206a0f4083 Fix Bug #478: 住院医生工作站检验申请详情「发往科室」显示为- — 根因:getLocationInfo 未对科室ID做类型归一化,recursionFun 中 item.id == targetDepartment 在类型不一致时匹配失败;修复:新增 normalizeOrgTreeIds 统一转 String,recursionFun 改用 String(item.id) === String(targetDepartment)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 18:08:44 +08:00
5e9aaebc7a Fix Bug #552: 根因+修复方案摘要 2026-05-19 18:08:44 +08:00
f925731f6f bug550 2026-05-19 18:08:44 +08:00
Ranyunqiao
156a3f0f24 bug 443 444 445 478 494 521 2026-05-19 18:08:43 +08:00
85d254990f Fix Bug #552: 双击待保存医嘱编辑保存后不应自动添加空医嘱 — 根因:handleSaveSign 中自动添加空行的条件缺少 isAdding.value 判断,导致双击编辑已有待保存医嘱也会触发 handleAddPrescription()
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 14:05:56 +08:00
37 changed files with 325 additions and 651 deletions

View File

@@ -1,27 +0,0 @@
# Bug #556 Analysis
## Title
【门诊医生站-检验】新增检验申请单时就诊卡号/执行时间未自动回显,且项目列表冗余显示"套餐"文字
## Root Cause Analysis
### Issue 1: 就诊卡号未自动回显
- **Code**: `inspectionApplication.vue:886` - `formData.medicalrecordNumber = props.patientInfo.identifierNo || ''`
- **Root Cause**: Logic is correct but depends on `props.patientInfo.identifierNo` being populated. The watch on `props.patientInfo` (line 2074) triggers `initData()`. The card number field itself is correctly bound. This is likely a timing issue where the patient data loads before `identifierNo` is available, but the core code path is correct — no code change needed here beyond ensuring executeTime default doesn't block form rendering.
### Issue 2: 执行时间未默认填充当前系统时间
- **Code**: `inspectionApplication.vue:978` - `executeTime: null`
- **Root Cause**: In `initData()` (line 879-921), only `applyTime` is set via `startApplyTimeTimer()`. `formData.executeTime` is never assigned a default value. Similarly in `resetForm()` (line 1550), `executeTime` remains `null`.
- **Fix**: Add `formData.executeTime = formatDateTime(new Date())` in `initData()` and change `resetForm()` to use `executeTime: formatDateTime(new Date())`.
### Issue 3: 项目列表冗余显示"套餐"文字
- **Code**: `inspectionApplication.vue:1190` - Already fixed with `packageName` check. But `inspectionApplication.vue:2000` in `loadApplicationToForm()` still uses loose check: `item.feePackageId != null || item.itemName?.includes('套餐')`.
- **Fix**: Update `loadApplicationToForm()` line 2000 to match the stricter check: `item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null' && item.packageName`.
## Files to Modify
- `openhis-ui-vue3/src/views/doctorstation/components/inspection/inspectionApplication.vue`
## Changes
1. `initData()`: Add `formData.executeTime = formatDateTime(new Date())` after line 899
2. `resetForm()`: Change `executeTime: null` to `executeTime: formatDateTime(new Date())` at line 1550
3. `loadApplicationToForm()`: Fix `isPackage` logic at line 2000

View File

@@ -1,53 +0,0 @@
# Bug #556 分析报告
## 问题描述
【门诊医生站-检验】新增检验申请单时:
1. 就诊卡号字段为空,未自动带出患者就诊卡号
2. 执行时间字段未自动填充,仅显示占位提示
3. 检验项目列表每条记录前均带"套餐"文字标签(冗余显示)
## 根因分析
### 问题1就诊卡号未自动回显
- 代码路径:`initData()``formData.medicalrecordNumber = props.patientInfo.identifierNo || ''`
- 数据绑定:`v-model="formData.medicalrecordNumber"`
- `props.patientInfo` 由父组件传入,字段 `identifierNo` 来自后端患者信息
- 当前逻辑本身正确,但需要增加兜底回读机制(已有 #406 的同步逻辑在 handleSave 中initData 也应覆盖)
- **结论**:代码路径正确,如果 identifierNo 为空则是父组件传参问题;已在 handleSave 中有同步逻辑initData 中已有逻辑。无需额外修复。
### 问题2执行时间未自动填充
- 根因:`formData.executeTime``formData` 初始化时line 978设为 `null`
- `initData()` 函数没有为 executeTime 设置默认值
- `resetForm()` 函数line 1550也将 executeTime 重置为 `null`
- 前端 datetime picker 在 `v-model``null` 时显示占位符 "选择执行时间"
- **修复方案**:在 `initData()` 中设置 `formData.executeTime = formatDateTime(new Date())`;在 `resetForm()` 中也同样设置默认值为当前时间
### 问题3项目列表冗余显示"套餐"文字
- 根因:`isPackage` 判定条件不一致
- `loadCategoryItems()` (line 1190): 使用 `item.feePackageId != null && ... && item.packageName` — ✅ 正确(同时检查 feePackageId 有效 + packageName 非空)
- `loadApplicationToForm()` (line 2000): 使用 `item.feePackageId != null || item.itemName?.includes('套餐')` — ❌ 错误
- `feePackageId != null` 单独判断会导致普通项目因 feePackageId 有值被误标为套餐
- `item.itemName?.includes('套餐')` 更是直接按名称文字判断,极不准确
- 影响位置:
- 检验项目选择区line 566`<el-tag v-if="item.isPackage">套餐</el-tag>`
- 已选项目列表line 617`<el-tag v-if="item.isPackage">套餐</el-tag>`
- 检验信息详情表格line 448`<el-tag v-if="scope.row.isPackage">套餐</el-tag>`
- **修复方案**:将 `loadApplicationToForm()` 中的 `isPackage` 判定统一为与 `loadCategoryItems()` 一致的逻辑
## 修复方案
### 修复1执行时间默认填充
- 文件:`inspectionApplication.vue`
- 位置:`initData()` 函数,在已有患者信息赋值后添加 `formData.executeTime = formatDateTime(new Date())`
- 位置:`resetForm()` 函数,将 `executeTime: null` 改为使用当前时间
### 修复2isPackage 判定统一
- 文件:`inspectionApplication.vue`
- 位置:`loadApplicationToForm()` 函数 line 2000
- 旧代码:`const isPackage = item.feePackageId != null || item.itemName?.includes('套餐')`
- 新代码:`const isPackage = item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null' && item.packageName`
## 验收标准
1. 新增检验申请单时执行时间字段自动填充当前系统时间YYYY-MM-DD HH:mm:ss 格式)
2. 检验项目列表中,只有真正的套餐项目前显示"套餐"标签,普通项目不显示
3. 就诊卡号在有患者信息时正常显示

View File

@@ -1,44 +0,0 @@
# 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;
```

View File

@@ -5,39 +5,37 @@
## 根因定位 ## 根因定位
**核心问题在 `OrganizationLocationAppServiceImpl.java:161-162`** **核心问题在 `OrganizationLocationAppServiceImpl.java:161-174`**
时间冲突检测使用了 `getOrgLocListByActivityDefinitionId()` 跨科室查询同一诊疗定义下的**所有**科室配置记录。 时间冲突检测的查询逻辑存在两个缺陷:
### 缺陷:跨科室误报冲突
### 缺陷1查询范围过窄
```java ```java
// 修复前:查询同一诊疗的所有科室配置(跨科室) // 只查同一科室 + 同一诊疗的记录
organizationLocationService.getOrgLocListByActivityDefinitionId(orgLoc.getActivityDefinitionId()); getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getOrganizationId(), 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 → "未知科室"
## 修复方案 ## 修复方案
**修改冲突检测范围**`getOrgLocListByActivityDefinitionId` 改为 `getOrgLocListByOrgIdAndActivityDefinitionId`,仅检测**同一科室内**的时间冲突。 1. **修改冲突检测范围**查询同一 `activityDefinitionId` 的所有记录(跨科室检测),而非仅限当前科室
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());
```
编译验证通过。

View File

@@ -1,8 +1,5 @@
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;
@@ -11,7 +8,6 @@ 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;
@@ -27,36 +23,6 @@ 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/+HHMMLocalDateTime 不含时区信息)
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);
}
};
/** /**
* 时区配置 * 时区配置
*/ */
@@ -68,9 +34,7 @@ public class ApplicationConfig {
// 设置日期格式为 yyyy/M/d HH:mm:ss支持多种格式反序列化 // 设置日期格式为 yyyy/M/d HH:mm:ss支持多种格式反序列化
builder.simpleDateFormat("yyyy/M/d HH:mm:ss"); builder.simpleDateFormat("yyyy/M/d HH:mm:ss");
// 添加JavaTimeModule支持用于LocalDateTime // 添加JavaTimeModule支持用于LocalDateTime
JavaTimeModule javaTimeModule = new JavaTimeModule(); builder.modules(new JavaTimeModule());
javaTimeModule.addDeserializer(LocalDateTime.class, LOCAL_DATE_TIME_DESERIALIZER);
builder.modules(javaTimeModule);
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss"))); builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy/M/d HH:mm:ss")));
}; };
} }

View File

@@ -158,10 +158,8 @@ 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.getOrgLocListByOrgIdAndActivityDefinitionId(orgLoc.getOrganizationId(), organizationLocationService.getOrgLocListByActivityDefinitionId(orgLoc.getActivityDefinitionId());
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;
@@ -171,9 +169,11 @@ 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());
String organizationName = org != null ? org.getName() : ("科室[" + organizationLocation.getOrganizationId() + "]已删除"); if (org == null) {
continue;
}
return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime() return R.fail("当前诊疗:" + activityName + CommonConstants.Common.DASH + orgLoc.getStartTime()
+ CommonConstants.Common.DASH + orgLoc.getEndTime() + "" + organizationName + "时间冲突"); + CommonConstants.Common.DASH + orgLoc.getEndTime() + "" + org.getName() + "时间冲突");
} }
if (orgLocQueryDto.getId() != null) { if (orgLocQueryDto.getId() != null) {

View File

@@ -215,9 +215,6 @@ 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);

View File

@@ -36,7 +36,4 @@ public class PerformInfoDto {
/** 分组id */ /** 分组id */
@JsonSerialize(using = ToStringSerializer.class) @JsonSerialize(using = ToStringSerializer.class)
private Long groupId; private Long groupId;
/** 退回原因 */
private String backReason;
} }

View File

@@ -147,6 +147,6 @@ public interface IDoctorStationAdviceAppService {
*/ */
IPage<SurgeryItemDto> getSurgeryPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey); IPage<SurgeryItemDto> getSurgeryPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey);
IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey, String categoryCode); IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey);
} }

View File

@@ -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, null); iMedicationRequestService.updateDraftStatusBatch(requestIdList, null, null);
// 尝试签退耗材请求(只有存在的才会更新) // 尝试签退耗材请求(只有存在的才会更新)
iDeviceRequestService.updateDraftStatusBatch(requestIdList); iDeviceRequestService.updateDraftStatusBatch(requestIdList);
// 尝试签退诊疗请求(只有存在的才会更新) // 尝试签退诊疗请求(只有存在的才会更新)
@@ -2343,52 +2343,21 @@ 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> medUpdateWrapper = new UpdateWrapper<>(); UpdateWrapper<MedicationRequest> updateWrapper = new UpdateWrapper<>();
medUpdateWrapper.set("group_id", null).in("id", idsToSetNull); updateWrapper.set("group_id", null).in("id", idsToSetNull);
iMedicationRequestService.update(medUpdateWrapper);
UpdateWrapper<ServiceRequest> srvUpdateWrapper = new UpdateWrapper<>(); // 执行更新
srvUpdateWrapper.set("group_id", null).in("id", idsToSetNull); iMedicationRequestService.update(updateWrapper);
iServiceRequestService.update(srvUpdateWrapper);
// DeviceRequest 使用 group_noString 类型)
UpdateWrapper<DeviceRequest> devUpdateWrapper = new UpdateWrapper<>();
devUpdateWrapper.set("group_no", null).in("id", idsToSetNull);
iDeviceRequestService.update(devUpdateWrapper);
} }
// 处理 groupId 非 null 的情况:按实际所属表分别更新 // 处理null的情况
List<UpdateGroupDto> nonNullGroupList = groupList.stream() List<MedicationRequest> medicationRequestList = groupList.stream().filter(dto -> dto.getGroupId() != null)
.filter(dto -> dto.getGroupId() != null).collect(Collectors.toList()); .map(dto -> new MedicationRequest().setId(dto.getRequestId()).setGroupId(dto.getGroupId()))
if (!nonNullGroupList.isEmpty()) { .collect(Collectors.toList());
for (UpdateGroupDto dto : nonNullGroupList) {
Long reqId = dto.getRequestId(); if (!medicationRequestList.isEmpty()) {
Long grpId = dto.getGroupId(); iMedicationRequestService.saveOrUpdateBatch(medicationRequestList);
// 先尝试药品表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);
}
}
} }
} }
@@ -2597,13 +2566,12 @@ public class DoctorStationAdviceAppServiceImpl implements IDoctorStationAdviceAp
} }
@Override @Override
public IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey, String categoryCode) { public IPage<SurgeryItemDto> getExaminationPage(Long organizationId, Integer pageNo, Integer pageSize, String searchKey) {
IPage<SurgeryItemDto> result = doctorStationAdviceAppMapper.getExaminationPage( IPage<SurgeryItemDto> result = doctorStationAdviceAppMapper.getExaminationPage(
new Page<>(pageNo, pageSize), new Page<>(pageNo, pageSize),
PublicationStatus.ACTIVE.getValue(), PublicationStatus.ACTIVE.getValue(),
organizationId, organizationId,
searchKey, searchKey);
categoryCode);
return result; return result;
} }

View File

@@ -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()).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false); Emr patientEmr = emrService.getOne(new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, emr.getEncounterId()));
boolean saveSuccess; boolean saveSuccess;
// 如果已经保存病历,再次保存走更新 // 如果已经保存病历,再次保存走更新
if (patientEmr != null) { if (patientEmr != null) {
@@ -126,10 +126,6 @@ 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);
@@ -144,12 +140,8 @@ 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).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false); Emr emrDetail = emrService.getOne(new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounterId));
if (emrDetail != null) { if (emrDetail != null) {
return R.ok(emrDetail); return R.ok(emrDetail);
} }
@@ -159,8 +151,7 @@ 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) {
// 住院病历存在,也返回数据 // 住院病历存在,也返回数据
@@ -249,7 +240,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()).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounter.getId())
); );
// 检查该就诊是否由指定医生负责 // 检查该就诊是否由指定医生负责
@@ -307,7 +298,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).orderByDesc(Emr::getCreateTime).last("LIMIT 1"), false new LambdaQueryWrapper<Emr>().eq(Emr::getEncounterId, encounterId)
); );
// 如果没有病历,则需要写病历 // 如果没有病历,则需要写病历

View File

@@ -226,9 +226,8 @@ public class DoctorStationAdviceController {
@RequestParam(value = "organizationId", required = false) Long organizationId, @RequestParam(value = "organizationId", required = false) Long organizationId,
@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(value = "pageSize", defaultValue = "500") Integer pageSize, @RequestParam(value = "pageSize", defaultValue = "500") Integer pageSize,
@RequestParam(value = "searchKey", defaultValue = "") String searchKey, @RequestParam(value = "searchKey", defaultValue = "") String searchKey) {
@RequestParam(value = "categoryCode", defaultValue = "23") String categoryCode) { return R.ok(iDoctorStationAdviceAppService.getExaminationPage(organizationId, pageNo, pageSize, searchKey));
return R.ok(iDoctorStationAdviceAppService.getExaminationPage(organizationId, pageNo, pageSize, searchKey, categoryCode));
} }
} }

View File

@@ -121,11 +121,6 @@ public class RequestBaseDto {
* 请求状态 * 请求状态
*/ */
private Integer statusEnum; private Integer statusEnum;
/**
* 退回原因
*/
private String reasonText;
private String statusEnum_enumText; private String statusEnum_enumText;
/** /**

View File

@@ -203,7 +203,6 @@ public interface DoctorStationAdviceAppMapper {
IPage<SurgeryItemDto> getExaminationPage(@Param("page") Page<SurgeryItemDto> page, IPage<SurgeryItemDto> getExaminationPage(@Param("page") Page<SurgeryItemDto> page,
@Param("statusEnum") Integer statusEnum, @Param("statusEnum") Integer statusEnum,
@Param("organizationId") Long organizationId, @Param("organizationId") Long organizationId,
@Param("searchKey") String searchKey, @Param("searchKey") String searchKey);
@Param("categoryCode") String categoryCode);
} }

View File

@@ -58,8 +58,6 @@ 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;
/** /**
@@ -234,7 +232,9 @@ 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,20 +262,8 @@ 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)) {
@@ -371,29 +359,6 @@ 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();
@@ -407,21 +372,15 @@ 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, backReason); serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
} }
if (!medRequestList.isEmpty()) { if (!medRequestList.isEmpty()) {
// 更新药品请求状态待发送 // 更新药品请求状态待发送
medicationRequestService.updateDraftStatusBatch( medicationRequestService.updateDraftStatusBatch(
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason); medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
} }
return R.ok(null, "退回成功"); return R.ok(null, "退回成功");
} }
@@ -565,10 +524,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
// 处理长期已发放的药品 // 处理长期已发放的药品
if (!longMedDispensedList.isEmpty()) { if (!longMedDispensedList.isEmpty()) {
// 生成退药单 // 生成退药单
this.creatRefundMedicationList(longMedDispensedList, procedureIdMap); this.creatRefundMedicationList(tempMedDispensedList, procedureIdMap);
// 药品退药请求状态变更(待退药)
medicationRequestService.updateCancelledStatusBatch(
longMedDispensedList.stream().map(MedicationDispense::getMedReqId).toList(), null, null);
} }
// 处理临时已发放药品 // 处理临时已发放药品
if (!tempMedDispensedList.isEmpty()) { if (!tempMedDispensedList.isEmpty()) {

View File

@@ -101,9 +101,6 @@ 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;

View File

@@ -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, null); serviceRequestService.updateDraftStatus(List.of(serviceRequest.getBasedOnId()), null, null);
if (result) { if (result) {
// 判断是否全部取消执行 // 判断是否全部取消执行
boolean exists = serviceRequestMapper.exists(new LambdaQueryWrapper<ServiceRequest>() boolean exists = serviceRequestMapper.exists(new LambdaQueryWrapper<ServiceRequest>()

View File

@@ -133,13 +133,47 @@ public class PatientInformationServiceImpl implements IPatientInformationService
@Override @Override
public IPage<PatientBaseInfoDto> getPatientInfo(PatientBaseInfoDto patientBaseInfoDto, String searchKey, public IPage<PatientBaseInfoDto> getPatientInfo(PatientBaseInfoDto patientBaseInfoDto, String searchKey,
Integer pageNo, Integer pageSize, HttpServletRequest request) { Integer pageNo, Integer pageSize, HttpServletRequest request) {
// 构建基础查询条件 // 获取登录者信息
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
Long userId = loginUser.getUserId();
Integer tenantId = loginUser.getTenantId().intValue();
// 先构建基础查询条件
QueryWrapper<PatientBaseInfoDto> queryWrapper = HisQueryUtils.buildQueryWrapper( QueryWrapper<PatientBaseInfoDto> queryWrapper = HisQueryUtils.buildQueryWrapper(
patientBaseInfoDto, searchKey, new HashSet<>(Arrays.asList(CommonConstants.FieldName.Name, patientBaseInfoDto, searchKey, new HashSet<>(Arrays.asList(CommonConstants.FieldName.Name,
CommonConstants.FieldName.BusNo, CommonConstants.FieldName.PyStr, CommonConstants.FieldName.WbStr)), CommonConstants.FieldName.BusNo, CommonConstants.FieldName.PyStr, CommonConstants.FieldName.WbStr)),
request); request);
// 检查是否是精确ID查询从门诊挂号页面跳转时使用
boolean hasExactIdQuery = (patientBaseInfoDto.getId() != null);
// 只有非精确ID查询时才添加医生患者过滤条件
if (!hasExactIdQuery) {
// 查询当前用户对应的医生信息
LambdaQueryWrapper<com.openhis.administration.domain.Practitioner> practitionerQuery = new LambdaQueryWrapper<>();
practitionerQuery.eq(com.openhis.administration.domain.Practitioner::getUserId, userId);
// 使用list()避免TooManyResultsException异常然后取第一个记录
List<com.openhis.administration.domain.Practitioner> practitionerList = practitionerService.list(practitionerQuery);
com.openhis.administration.domain.Practitioner practitioner = practitionerList != null && !practitionerList.isEmpty() ? practitionerList.get(0) : null;
// 如果当前用户是医生,添加医生患者过滤条件
if (practitioner != null) {
// 查询该医生作为接诊医生ADMITTER, code="1"和挂号医生REGISTRATION_DOCTOR, code="12"的所有就诊记录的患者ID
List<Long> doctorPatientIds = patientManageMapper.getPatientIdsByPractitionerId(
practitioner.getId(),
Arrays.asList(ParticipantType.ADMITTER.getCode(), ParticipantType.REGISTRATION_DOCTOR.getCode()),
tenantId);
if (doctorPatientIds != null && !doctorPatientIds.isEmpty()) {
// 添加患者ID过滤条件 - 注意:这里使用列名而不是表别名
queryWrapper.in("id", doctorPatientIds);
} else {
// 如果没有相关患者,返回空结果
queryWrapper.eq("id", -1); // 设置一个不存在的ID
}
}
// 如果不是医生,查询所有患者
}
IPage<PatientBaseInfoDto> patientInformationPage IPage<PatientBaseInfoDto> patientInformationPage
= patientManageMapper.getPatientPage(new Page<>(pageNo, pageSize), queryWrapper); = patientManageMapper.getPatientPage(new Page<>(pageNo, pageSize), queryWrapper);

View File

@@ -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.getEffectiveOrgId()); // 执行科室 longServiceRequest.setOrgId(regAdviceSaveDto.getPositionId()); // 执行科室
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.getEffectiveOrgId()); // 执行科室 tempServiceRequest.setOrgId(regAdviceSaveDto.getPositionId()); // 执行科室
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, null); iMedicationRequestService.updateDraftStatusBatch(medicineRequestIds, null, null);
} }
if (!activityRequestIds.isEmpty()) { if (!activityRequestIds.isEmpty()) {
// 根据请求id更新请求状态 // 根据请求id更新请求状态

View File

@@ -10,4 +10,8 @@ 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;
} }

View File

@@ -516,7 +516,6 @@
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'
@@ -578,7 +577,6 @@
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'
@@ -639,7 +637,6 @@
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'
@@ -694,7 +691,6 @@
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'
@@ -751,7 +747,6 @@
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
@@ -902,7 +897,7 @@
LIMIT #{limit} OFFSET #{offset} LIMIT #{limit} OFFSET #{offset}
</select> </select>
<!-- 检查/检验项目专用分页查询:仅查指定 category_code + 定价,无库存/草稿库存/取药科室等无关逻辑 --> <!-- 检查项目专用分页查询:仅查检查(23) + 定价,无库存/草稿库存/取药科室等无关逻辑 -->
<select id="getExaminationPage" resultType="com.openhis.web.doctorstation.dto.SurgeryItemDto"> <select id="getExaminationPage" resultType="com.openhis.web.doctorstation.dto.SurgeryItemDto">
SELECT DISTINCT ON (t1.ID) SELECT DISTINCT ON (t1.ID)
t1.ID AS advice_definition_id, t1.ID AS advice_definition_id,
@@ -924,7 +919,7 @@
ON t3.id = t1.org_id ON t3.id = t1.org_id
AND t3.delete_flag = '0' AND t3.delete_flag = '0'
WHERE t1.delete_flag = '0' WHERE t1.delete_flag = '0'
AND t1.category_code = #{categoryCode} AND t1.category_code = '23'
<if test="searchKey != null and searchKey != ''"> <if test="searchKey != null and searchKey != ''">
AND (t1.name ILIKE '%' || #{searchKey} || '%' OR t1.py_str ILIKE '%' || #{searchKey} || '%') AND (t1.name ILIKE '%' || #{searchKey} || '%' OR t1.py_str ILIKE '%' || #{searchKey} || '%')
</if> </if>

View File

@@ -1,7 +1,6 @@
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;
@@ -107,12 +106,10 @@ 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-删除) */

View File

@@ -1,7 +1,6 @@
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;
@@ -76,12 +75,10 @@ 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-删除) */

View File

@@ -111,9 +111,6 @@ public class MedicationRequest extends HisBaseEntity {
/** 支持用药信息 */ /** 支持用药信息 */
private String supportInfo; private String supportInfo;
/** 退回原因 */
private String backReason;
/** 请求开始时间 */ /** 请求开始时间 */
private Date reqAuthoredTime; private Date reqAuthoredTime;

View File

@@ -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, String backReason); void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate);
/** /**
* 更新请求状态:取消 * 更新请求状态:取消

View File

@@ -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, String backReason) { public void updateDraftStatusBatch(List<Long> requestIdList, Long practitionerId, Date checkDate) {
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,9 +54,6 @@ 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);
} }

View File

@@ -79,13 +79,11 @@ public class OpSchedule extends HisBaseEntity {
private String surgerySite; private String surgerySite;
/** 入院时间 */ /** 入院时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime admissionTime; private LocalDateTime admissionTime;
/** 入手术室时间 */ /** 入手术室时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime entryTime; private LocalDateTime entryTime;
/** 手术室编码 */ /** 手术室编码 */
@@ -144,23 +142,19 @@ public class OpSchedule extends HisBaseEntity {
private String assistant3Code; private String assistant3Code;
/** 手术开始时间 */ /** 手术开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime startTime; private LocalDateTime startTime;
/** 手术结束时间 */ /** 手术结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime; private LocalDateTime endTime;
/** 麻醉开始时间 */ /** 麻醉开始时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime anesStart; private LocalDateTime anesStart;
/** 麻醉结束时间 */ /** 麻醉结束时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime anesEnd; private LocalDateTime anesEnd;
/** 手术状态 */ /** 手术状态 */

View File

@@ -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, String backReason); void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate);
/** /**
* 更新服务状态:待发送 * 更新服务状态:待发送

View File

@@ -172,15 +172,9 @@ public class ServiceRequestServiceImpl extends ServiceImpl<ServiceRequestMapper,
* @param checkDate 校对时间 * @param checkDate 校对时间
*/ */
@Override @Override
public void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate, String backReason) { public void updateDraftStatus(List<Long> serviceRequestIdList, Long practitionerId, Date checkDate) {
ServiceRequest updateEntity = new ServiceRequest() baseMapper.update(new ServiceRequest().setStatusEnum(RequestStatus.DRAFT.getValue())
.setStatusEnum(RequestStatus.DRAFT.getValue()) .setPerformerCheckId(SecurityUtils.getLoginUser().getPractitionerId()).setCheckTime(DateUtils.getNowDate()),
.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()));
} }

View File

@@ -1,13 +0,0 @@
-- 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
$$;

View File

@@ -220,18 +220,3 @@ export function getSlotStatusDescription(value) {
export function getSlotStatusClass(status) { export function getSlotStatusClass(status) {
return SlotStatusClassMap[status] || 'status-unbooked'; return SlotStatusClassMap[status] || 'status-unbooked';
} }
/**
* 诊疗项目分类代码(对应后端 ActivityDefCategory 枚举)
* wor_activity_definition.category_code 字段
*/
export const ActivityCategory = {
/** 治疗 */
TREATMENT: '21',
/** 检验 */
PROOF: '22',
/** 检查 */
TEST: '23',
/** 手术 */
PROCEDURE: '24',
};

View File

@@ -898,9 +898,6 @@ const initData = async () => {
// 申请日期实时更新(启动定时器) // 申请日期实时更新(启动定时器)
startApplyTimeTimer() startApplyTimeTimer()
// 执行时间默认填充当前系统时间
formData.executeTime = formatDateTime(new Date())
// 获取主诊断信息 // 获取主诊断信息
try { try {
const res = await getEncounterDiagnosis(props.patientInfo.encounterId) const res = await getEncounterDiagnosis(props.patientInfo.encounterId)
@@ -1188,9 +1185,9 @@ const loadCategoryItems = async (categoryKey, loadMore = false) => {
// 映射数据格式(从检验项目维护页面的数据结构映射) // 映射数据格式(从检验项目维护页面的数据结构映射)
const mappedItems = records.map(item => { const mappedItems = records.map(item => {
// 套餐项目处理:需同时满足 feePackageId 有效且 packageName 非空 // 套餐项目处理:套餐项目使用套餐金额,普通项目使用零售价
// BugFix#556: 增加 packageName 联合判断,避免普通项目因 feePackageId 有值被误标为套餐 // BugFix#404: 增加对空字符串的判断避免空字符串被误认为有效套餐ID
const isPackage = Boolean(item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null' && item.packageName) const isPackage = item.feePackageId != null && item.feePackageId !== '' && item.feePackageId !== 'null'
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 +1675,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: Boolean(item.isPackage), isPackage: item.isPackage || false,
sampleType: item.sampleType || '', sampleType: item.sampleType || '',
unit: item.unit || '' unit: item.unit || ''
})) }))

View File

@@ -17,14 +17,17 @@
style="width: 300px; margin-bottom: 10px" style="width: 300px; margin-bottom: 10px"
> >
<template #append> <template #append>
<el-button @click="handleSearch" :loading="loading">搜索</el-button> <el-button @click="handleSearch">搜索</el-button>
</template> </template>
</el-input> </el-input>
<span class="total-count"> {{ totalCount }} </span> <span v-if="!searchKey" class="total-count"> {{ totalCount }} </span>
<span v-else class="total-count">搜索到 {{ filteredCount }} / {{ totalCount }} </span>
</div> </div>
<el-transfer <el-transfer
v-model="transferValue" v-model="transferValue"
:data="transferData" :data="transferData"
filter-placeholder="项目代码/名称"
filterable
:titles="['未选择', '已选择']" :titles="['未选择', '已选择']"
/> />
</div> </div>
@@ -133,8 +136,7 @@
<script setup name="LaboratoryTests"> <script setup name="LaboratoryTests">
import {getCurrentInstance, nextTick, onMounted, reactive, ref, watch, computed} from 'vue'; import {getCurrentInstance, nextTick, onMounted, reactive, ref, watch, computed} from 'vue';
import {patientInfo} from '../../../store/patient.js'; import {patientInfo} from '../../../store/patient.js';
import {getExaminationPage, saveInspection} from './api'; import {getApplicationList, saveInspection} from './api';
import {ActivityCategory} from '@/utils/medicalConstants';
import {getDepartmentList} from '@/api/public.js'; import {getDepartmentList} from '@/api/public.js';
import {getEncounterDiagnosis} from '../../api.js'; import {getEncounterDiagnosis} from '../../api.js';
import {ElMessage} from 'element-plus'; import {ElMessage} from 'element-plus';
@@ -171,8 +173,9 @@ const skipDeptAutoFill = ref(false);
// 将已加载的全部数据转为 transfer 组件所需的格式 // 将已加载的全部数据转为 transfer 组件所需的格式
const buildTransferData = (records) => { const buildTransferData = (records) => {
return records.map((item) => { return records.map((item) => {
const price = item.price != null ? Number(item.price).toFixed(2) : '0.00'; const priceInfo = item.priceList?.[0] || {};
const unit = item.unitCodeDictText || item.unitCode || ''; const price = priceInfo.price != null ? Number(priceInfo.price).toFixed(2) : '0.00';
const unit = item.unitCode_dictText || item.unitCode || '';
return { return {
adviceDefinitionId: item.adviceDefinitionId, adviceDefinitionId: item.adviceDefinitionId,
orgId: item.orgId, orgId: item.orgId,
@@ -182,8 +185,7 @@ const buildTransferData = (records) => {
}); });
}; };
const selectedItemsCache = ref(new Map()); // 加载全部数据(不分页,一次性拉取)
const loadAllData = async () => { const loadAllData = async () => {
if (!patientInfo.value?.inHospitalOrgId) { if (!patientInfo.value?.inHospitalOrgId) {
applicationListAll.value = []; applicationListAll.value = [];
@@ -191,12 +193,13 @@ const loadAllData = async () => {
} }
loading.value = true; loading.value = true;
try { try {
const res = await getExaminationPage({ // 使用大 pageSize 一次性拉取所有启用状态的检验类诊疗项目
pageSize: 100, const res = await getApplicationList({
pageSize: 9999,
pageNo: 1, pageNo: 1,
categoryCode: ActivityCategory.PROOF, categoryCode: '22',
organizationId: patientInfo.value.inHospitalOrgId, organizationId: patientInfo.value.inHospitalOrgId,
searchKey: searchKey.value, adviceTypes: [3], // 1 药品 2 耗材 3 诊疗
}); });
if (res.code !== 200) { if (res.code !== 200) {
proxy.$message.error(res.message); proxy.$message.error(res.message);
@@ -205,9 +208,8 @@ const loadAllData = async () => {
} }
applicationListAll.value = res.data?.records || []; applicationListAll.value = res.data?.records || [];
totalCount.value = res.data?.total || 0; totalCount.value = res.data?.total || 0;
if (!searchKey.value) { // 检验项目列表为异步加载,编辑回显必须在数据就绪后执行,否则已选区一直为空
applyEditTransferSelection(); applyEditTransferSelection()
}
} catch (e) { } catch (e) {
proxy.$message.error('获取检验项目列表失败'); proxy.$message.error('获取检验项目列表失败');
applicationListAll.value = []; applicationListAll.value = [];
@@ -216,18 +218,32 @@ const loadAllData = async () => {
} }
}; };
const transferData = computed(() => buildTransferData(applicationListAll.value)); // 根据搜索关键词过滤数据
const filterData = (key) => {
if (!key || key.trim() === '') {
return applicationListAll.value;
}
const lowerKey = key.toLowerCase().trim();
return applicationListAll.value.filter((item) => {
return (
item.adviceName?.toLowerCase().includes(lowerKey) ||
item.pyStr?.toLowerCase().includes(lowerKey) ||
item.adviceBusNo?.toLowerCase().includes(lowerKey)
);
});
};
// transfer 组件实际显示的数据(受搜索词影响)
const transferData = computed(() => buildTransferData(filterData(searchKey.value)));
// 当前显示的条数
const filteredCount = computed(() => filterData(searchKey.value).length);
const getList = async () => { const getList = async () => {
await loadAllData(); await loadAllData();
}; };
let searchTimer = null;
const handleSearch = () => { const handleSearch = () => {
clearTimeout(searchTimer); // 搜索时保持已选中的项目不受影响
searchTimer = setTimeout(() => {
loadAllData();
}, 300);
}; };
// 编辑初始化标志:避免 applyEditTransferSelection 设置 transferValue 时触发 projectWithDepartment 覆盖 descJson 中的科室值 // 编辑初始化标志:避免 applyEditTransferSelection 设置 transferValue 时触发 projectWithDepartment 覆盖 descJson 中的科室值
const isInitializing = ref(false); const isInitializing = ref(false);
@@ -286,17 +302,13 @@ const projectWithDepartment = (selectProjectIds, type) => {
const arr = []; const arr = [];
// 根据选中的项目id查找对应的项目从全部原始数据中查找 // 根据选中的项目id查找对应的项目从全部原始数据中查找
selectProjectIds.forEach((element) => { selectProjectIds.forEach((element) => {
let searchData = applicationListAll.value.find((item) => { const searchData = applicationListAll.value.find((item) => {
return element == item.adviceDefinitionId; return element == item.adviceDefinitionId;
}); });
if (!searchData) {
searchData = selectedItemsCache.value.get(element);
}
if (searchData) { if (searchData) {
const priceInfo = searchData.priceList?.[0] || {}; const priceInfo = searchData.priceList?.[0] || {};
const price = searchData.price != null ? Number(searchData.price).toFixed(2) const price = priceInfo.price != null ? Number(priceInfo.price).toFixed(2) : '0.00';
: priceInfo.price != null ? Number(priceInfo.price).toFixed(2) : '0.00'; const unit = searchData.unitCode_dictText || searchData.unitCode || '';
const unit = searchData.unitCodeDictText || searchData.unitCode_dictText || searchData.unitCode || '';
arr.push({ arr.push({
adviceDefinitionId: searchData.adviceDefinitionId, adviceDefinitionId: searchData.adviceDefinitionId,
orgId: searchData.orgId, orgId: searchData.orgId,
@@ -359,12 +371,6 @@ watch(
(newValue) => { (newValue) => {
if (skipDeptAutoFill.value) return; if (skipDeptAutoFill.value) return;
if (isInitializing.value) return; if (isInitializing.value) return;
newValue.forEach((id) => {
if (!selectedItemsCache.value.has(id)) {
const item = applicationListAll.value.find((i) => i.adviceDefinitionId == id);
if (item) selectedItemsCache.value.set(id, item);
}
});
projectWithDepartment(newValue, 1); projectWithDepartment(newValue, 1);
} }
); );
@@ -449,14 +455,13 @@ watch(
} }
) )
// 编辑模式下,项目字典首次加载完成后回显已选项目(搜索刷新不重置) // 编辑模式下,项目字典加载完成后重新回显已选项目
watch( watch(
() => applicationListAll.value, () => applicationListAll.value,
() => { () => {
if (!props.editData?.requestFormId) return; if (!props.editData?.requestFormId) return;
if (!props.editData.requestFormDetailList?.length) return; if (!props.editData.requestFormDetailList?.length) return;
if (!applicationListAll.value.length) return; if (!applicationListAll.value.length) return;
if (searchKey.value) return;
const selectedIds = []; const selectedIds = [];
props.editData.requestFormDetailList.forEach((detail) => { props.editData.requestFormDetailList.forEach((detail) => {
@@ -481,29 +486,26 @@ const submit = () => {
if (!projectWithDepartment(transferValue.value, 2)) { if (!projectWithDepartment(transferValue.value, 2)) {
return; return;
} }
let applicationListAllFilter = transferValue.value.map((id) => { let applicationListAllFilter = applicationListAll.value.filter((item) => {
let item = applicationListAll.value.find((i) => i.adviceDefinitionId == id); return transferValue.value.includes(item.adviceDefinitionId);
if (!item) { });
item = selectedItemsCache.value.get(id); applicationListAllFilter = applicationListAllFilter.map((item) => {
}
if (!item) return null;
const priceInfo = item.priceList?.[0] || {};
return { return {
adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */, adviceDefinitionId: item.adviceDefinitionId /** 诊疗定义id */,
quantity: 1, // /** 请求数量 */ quantity: 1, // /** 请求数量 */
unitCode: item.unitCode || priceInfo.unitCode || '' /** 请求单位编码 */, unitCode: item.priceList[0].unitCode /** 请求单位编码 */,
unitPrice: item.price ?? priceInfo.price ?? 0 /** 单价 */, unitPrice: item.priceList[0].price /** 单价 */,
totalPrice: item.price ?? priceInfo.price ?? 0 /** 总价 */, totalPrice: item.priceList[0].price /** 总价 */,
positionId: form.targetDepartment || item.positionId, // 用户指定发往科室优先于项目默认执行科室 positionId: form.targetDepartment || item.positionId, // 用户指定发往科室优先于项目默认执行科室
ybClassEnum: item.ybClassEnum || '', //类别医保编码 ybClassEnum: item.ybClassEnum, //类别医保编码
conditionId: item.conditionId || '', //诊断ID conditionId: item.conditionId, //诊断ID
encounterDiagnosisId: item.encounterDiagnosisId || '', //就诊诊断id encounterDiagnosisId: item.encounterDiagnosisId, //就诊诊断id
adviceType: item.adviceType || 3, ///** 医嘱类型 */ adviceType: item.adviceType, ///** 医嘱类型 */
definitionId: item.chargeItemDefinitionId || priceInfo.definitionId || '', //费用定价主表ID */ definitionId: item.priceList[0].definitionId, //费用定价主表ID */
definitionDetailId: item.definitionDetailId || priceInfo.definitionDetailId || '', //费用定价子表ID */ definitionDetailId: item.definitionDetailId, //费用定价子表ID */
accountId: patientInfo.value.accountId, // // 账户id accountId: patientInfo.value.accountId, // // 账户id
}; };
}).filter(Boolean); });
const params = { const params = {
activityList: applicationListAllFilter, activityList: applicationListAllFilter,
patientId: patientInfo.value.patientId, //患者ID patientId: patientInfo.value.patientId, //患者ID
@@ -518,7 +520,6 @@ const submit = () => {
if (res.code === 200) { if (res.code === 200) {
proxy.$message.success(isEditMode.value ? '修改成功' : res.msg); proxy.$message.success(isEditMode.value ? '修改成功' : res.msg);
transferValue.value = []; transferValue.value = [];
selectedItemsCache.value.clear();
emits('submitOk'); emits('submitOk');
} else { } else {
proxy.$message.error(res.message); proxy.$message.error(res.message);

View File

@@ -207,7 +207,6 @@ import {patientInfo} from '../../../store/patient.js';
import {getDepartmentList} from '@/api/public.js'; import {getDepartmentList} from '@/api/public.js';
import {getEncounterDiagnosis} from '../../api.js'; import {getEncounterDiagnosis} from '../../api.js';
import {getExaminationPage, saveCheckd} from './api'; import {getExaminationPage, saveCheckd} from './api';
import {ActivityCategory} from '@/utils/medicalConstants';
import {ElMessage, ElMessageBox} from 'element-plus'; import {ElMessage, ElMessageBox} from 'element-plus';
import {WarningFilled, Warning, Refresh, Files, Document, EditPen, Aim, DocumentCopy} from '@element-plus/icons-vue'; import {WarningFilled, Warning, Refresh, Files, Document, EditPen, Aim, DocumentCopy} from '@element-plus/icons-vue';
@@ -277,7 +276,6 @@ const getList = () => {
pageNo: 1, pageNo: 1,
pageSize: 5000, pageSize: 5000,
searchKey: '', searchKey: '',
categoryCode: ActivityCategory.TEST,
}) })
.then((res) => { .then((res) => {
if (res.code === 200 && res.data?.records) { if (res.code === 200 && res.data?.records) {

View File

@@ -198,7 +198,7 @@
v-model="scope.row.adviceName" v-model="scope.row.adviceName"
placeholder="请选择项目" placeholder="请选择项目"
@input="handleChange" @input="handleChange"
@focus="handleFocus(scope.row, scope.$index)" @click="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,10 +640,6 @@ 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(); // 更新标记
@@ -900,16 +896,31 @@ 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;
let categoryCode = ''; // 用 adviceType + 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);
categoryCode = selectedItem ? selectedItem.categoryCode : (row.categoryCode || ''); // If the row has an explicit adviceType (saved/existing row), use its own 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);
} }
adviceQueryParams.value = { adviceType, categoryCode, searchKey: '' }; }, 100);
}
});
});
} }
function handleBlur(row) { function handleBlur(row) {
@@ -918,26 +929,22 @@ function handleBlur(row) {
function handleChange(value) { function handleChange(value) {
adviceQueryParams.value.searchKey = value; adviceQueryParams.value.searchKey = value;
// @focus 已先于 @input 执行rowIndex 必定有效 // 搜索词变化时,调用当前行子组件的 refresh 方法
const currentIndex = rowIndex.value; const index = rowIndex.value;
if (currentIndex < 0) return; if (index >= 0) {
const row = filterPrescriptionList.value[currentIndex]; const tableRef = Array.isArray(adviceTableRef.value) ? adviceTableRef.value[index] : adviceTableRef.value;
// 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;
let categoryCode = ''; // 用 adviceType + 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);
categoryCode = selectedItem ? selectedItem.categoryCode : (adviceQueryParams.value.categoryCode || ''); // 修复Bug #486当行没有显式选择医嘱类型时不传categoryCode让搜索在全药库中进行
} const categoryCode = selectedItem ? selectedItem.categoryCode : (row?.adviceType !== undefined ? (adviceQueryParams.value.categoryCode || '') : '');
tableRef.refresh(adviceType, categoryCode, value); tableRef.refresh(adviceType, categoryCode, value);
} }
} }
}
/** /**
* 选择药品回调 * 选择药品回调
@@ -1572,24 +1579,11 @@ function handleSaveGroup(orderGroupList) {
let successCount = 0; let successCount = 0;
// 收集所有要添加的新行,最后统一 unshift 到数组开头(置顶显示)
const newRows = [];
// 记录循环前的数组长度,用于清理循环中创建的临时行
const originalLength = prescriptionList.value.length;
orderGroupList.forEach((item) => { orderGroupList.forEach((item) => {
// 使用临时索引,先追加到末尾用于 setValue 填充 rowIndex.value = prescriptionList.value.length;
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;
} }
@@ -1615,12 +1609,18 @@ function handleSaveGroup(orderGroupList) {
therapyEnum: item.orderDetailInfos?.therapyEnum || '1', therapyEnum: item.orderDetailInfos?.therapyEnum || '1',
}; };
rowIndex.value = tempIndex; // 预初始化空行(组套项带预填值,设为 false 让明细字段在表格中直接展示)
prescriptionList.value[rowIndex.value] = {
uniqueKey: nextId.value++,
isEdit: false,
statusEnum: 1,
};
setValue(mergedDetail); setValue(mergedDetail);
// 创建新的处方项目 // 创建新的处方项目
const newRow = { const newRow = {
...prescriptionList.value[tempIndex], ...prescriptionList.value[rowIndex.value],
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[tempIndex].requestId ? '2' : '1', dbOpType: prescriptionList.value[rowIndex.value].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[tempIndex]?.therapyEnum || mergedDetail.therapyEnum || '1', therapyEnum: prescriptionList.value[rowIndex.value]?.therapyEnum || mergedDetail.therapyEnum || '1',
// 🔧 修复:确保组套医嘱的 categoryEnum 被正确映射,防止后端 NPE // 🔧 修复:确保组套医嘱的 categoryEnum 被正确映射,防止后端 NPE
categoryEnum: mergedDetail?.categoryEnum || mergedDetail?.categoryCode || item?.categoryCode, categoryEnum: mergedDetail?.categoryEnum || mergedDetail?.categoryCode || item?.categoryCode,
}; };
@@ -1663,14 +1663,11 @@ function handleSaveGroup(orderGroupList) {
} }
newRow.contentJson = JSON.stringify(newRow); newRow.contentJson = JSON.stringify(newRow);
newRows.push(newRow); prescriptionList.value[rowIndex.value] = 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} 个医嘱项`);
} }
} }

View File

@@ -99,7 +99,6 @@ function handleClick(tabName) {
break; break;
case 'cancel': case 'cancel':
exeStatus.value = 9; exeStatus.value = 9;
requestStatus.value = RequestStatus.CANCELLED;
break; break;
} }

View File

@@ -740,8 +740,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 结果表格卡片 --> <!-- 结果表格 -->
<el-card shadow="never" class="apply-card">
<el-table <el-table
ref="applyTableRef" ref="applyTableRef"
v-loading="applyLoading" v-loading="applyLoading"
@@ -750,7 +749,8 @@
@row-click="handleApplyRowClick" @row-click="handleApplyRowClick"
:row-class-name="tableRowClassName" :row-class-name="tableRowClassName"
style="width: 100%" style="width: 100%"
max-height="320" max-height="340"
:scroll="{ y: 340 }"
> >
<el-table-column type="selection" width="55" :selectable="handleSelectable" /> <el-table-column type="selection" width="55" :selectable="handleSelectable" />
<el-table-column label="ID" align="center" width="80" fixed> <el-table-column label="ID" align="center" width="80" fixed>
@@ -779,20 +779,19 @@
</el-table-column> </el-table-column>
<el-table-column label="主刀医生" align="center" width="100" prop="mainSurgeonName" /> <el-table-column label="主刀医生" align="center" width="100" prop="mainSurgeonName" />
</el-table> </el-table>
<!-- 分页在卡片内部 -->
<div class="apply-pagination"> <!-- 底部分页区 -->
<div class="pagination-container apply-pagination">
<pagination <pagination
v-show="applyTotal > 0" v-show="applyTotal > 0"
:total="applyTotal" :total="applyTotal"
:page="applyQueryParams.pageNo" :page="applyQueryParams.pageNo"
:limit="applyQueryParams.pageSize" :limit="applyQueryParams.pageSize"
layout="total, sizes, prev, pager, next"
@update:page="val => applyQueryParams.pageNo = val" @update:page="val => applyQueryParams.pageNo = val"
@update:limit="val => applyQueryParams.pageSize = val" @update:limit="val => applyQueryParams.pageSize = val"
@pagination="getSurgicalScheduleList" @pagination="getSurgicalScheduleList"
/> />
</div> </div>
</el-card>
<!-- 底部操作区 --> <!-- 底部操作区 -->
<template #footer> <template #footer>
<div class="dialog-footer" style="padding-top: 12px; border-top: 1px solid #ebeef5"> <div class="dialog-footer" style="padding-top: 12px; border-top: 1px solid #ebeef5">
@@ -1818,14 +1817,11 @@ function handleQuoteBilling() {
temporaryBillingMedicines.value = [] temporaryBillingMedicines.value = []
temporaryAdvices.value = [] temporaryAdvices.value = []
// 🔧 修复 Bug #444: 统一过滤逻辑,与 handleMedicalAdvice 保持一致 // 🔧 修复 Bug #445: 只保留药品类型adviceType=1过滤掉耗材(2)和诊疗项目(3/6)
// 1. 使用 Number() + snake_case 回退,避免类型转换导致过滤失效 // 同时过滤掉已有 requestId 的项目(已生成医嘱的不需要再次显示在"待生成"列表中)
// 2. 增加关键词二次过滤,排除手术/检查/诊疗等非药品项目 // 先提取已签发项目(statusEnum=2)填充已生成列表
const filteredItems = res.data.filter(item => { const activeItems = 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;
@@ -2343,35 +2339,19 @@ function getRowClassName({ row, rowIndex }) {
margin-left: 10px; margin-left: 10px;
} }
/* 手术申请查询弹窗 — flex 布局确保分页不溢出 */ /* 手术申请查询弹窗 — 分页与footer间距 */
.surgery-apply-dialog :deep(.el-dialog__body) { .surgery-apply-dialog :deep(.el-dialog__body) {
display: flex;
flex-direction: column;
padding-bottom: 16px; padding-bottom: 16px;
overflow: hidden;
} }
.surgery-apply-dialog :deep(.el-dialog__footer) { .surgery-apply-dialog :deep(.el-dialog__footer) {
padding-top: 0; padding-top: 8px;
}
.surgery-apply-dialog :deep(.apply-card) {
flex: 1;
overflow: hidden;
min-height: 0;
}
.surgery-apply-dialog :deep(.apply-card .el-card__body) {
overflow-y: auto;
} }
.surgery-apply-dialog :deep(.apply-pagination) { .surgery-apply-dialog :deep(.apply-pagination) {
display: flex; padding-top: 12px;
justify-content: flex-end; padding-bottom: 16px;
padding-top: 8px;
border-top: 1px solid #ebeef5;
}
.surgery-apply-dialog :deep(.apply-pagination .pagination-container) {
margin-top: 0;
} }
.surgery-apply-dialog :deep(.apply-pagination .el-pagination) { .surgery-apply-dialog :deep(.apply-pagination .el-pagination) {
position: static; margin-right: 80px;
} }
/* 选中行样式 */ /* 选中行样式 */
@@ -2387,33 +2367,17 @@ function getRowClassName({ row, rowIndex }) {
<style> <style>
/* 手术申请查询弹窗 — 非 scoped 确保穿透 teleport */ /* 手术申请查询弹窗 — 非 scoped 确保穿透 teleport */
.surgery-apply-dialog .el-dialog__body {
display: flex !important;
flex-direction: column !important;
padding-bottom: 16px !important;
overflow: hidden !important;
}
.surgery-apply-dialog .el-dialog__footer {
padding-top: 0 !important;
}
.surgery-apply-dialog .apply-card {
flex: 1 !important;
overflow: hidden !important;
min-height: 0 !important;
}
.surgery-apply-dialog .apply-card .el-card__body {
overflow-y: auto !important;
}
.surgery-apply-dialog .apply-pagination { .surgery-apply-dialog .apply-pagination {
display: flex !important; padding-top: 12px !important;
justify-content: flex-end !important; padding-bottom: 16px !important;
padding-top: 8px !important;
border-top: 1px solid #ebeef5 !important;
}
.surgery-apply-dialog .apply-pagination .pagination-container {
margin-top: 0 !important;
} }
.surgery-apply-dialog .apply-pagination .el-pagination { .surgery-apply-dialog .apply-pagination .el-pagination {
position: static !important; margin-right: 80px !important;
}
.surgery-apply-dialog .el-dialog__body {
padding-bottom: 16px !important;
}
.surgery-apply-dialog .el-dialog__footer {
padding-top: 8px !important;
} }
</style> </style>