fix(#613): 医嘱退回流程完善 — 前端退回原因必填弹窗 + 后端存储退回原因

根因(全链路6环分析):
- ① 前端/页面  handleCancel() 直接调 API,无退回原因输入弹窗
- ② Controller  不涉及 backReason — 纯转发,无需修改
- ③ Service  adviceReject() 从 DTO 读取 list 但不提取 backReason,硬编码传 null
- ④ Mapper/DB  backReason 参数已就绪但上游传 null 导致不写入
- ⑤ 医生端  因 DB 无数据,无法展示退回原因

修复:
- 前端: handleCancel() 改为弹对话框,新增 confirmCancel() 校验必填后传 backReason
- 后端: adviceReject() 从 PerformInfoDto 提取 backReason 传给 updateDraftStatus/updateDraftStatusBatch

全链路状态流转:
护士选医嘱 → 点退回 → 弹窗要求输入原因 → 确定 → API传backReason → DB保存 → 医生端可显示
This commit is contained in:
2026-05-29 14:15:26 +08:00
parent 3997c02564
commit 5b80695669
2 changed files with 55 additions and 9 deletions

View File

@@ -58,6 +58,7 @@ import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.Objects;
import java.util.stream.Collectors;
/**
@@ -413,15 +414,21 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
}
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
Date checkDate = new Date();
// 从请求中提取退回原因(所有项目共享同一原因)
String backReason = performInfoList.stream()
.map(PerformInfoDto::getBackReason)
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
if (!serviceRequestList.isEmpty()) {
// 更新服务请求状态待发送
serviceRequestService.updateDraftStatus(
serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, null);
serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason);
}
if (!medRequestList.isEmpty()) {
// 更新药品请求状态待发送
medicationRequestService.updateDraftStatusBatch(
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, null);
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate, backReason);
}
return R.ok(null, "退回成功");
}

View File

@@ -226,6 +226,25 @@
/>
</div>
</div>
<!-- 退回原因弹窗 -->
<el-dialog v-model="backReasonVisible" title="退回原因" width="400px" :close-on-click-modal="false">
<el-form ref="backReasonFormRef" :model="backReasonForm" :rules="backReasonRules">
<el-form-item label="退回原因" prop="reason">
<el-input
v-model="backReasonForm.reason"
type="textarea"
:rows="4"
placeholder="请输入退回原因(必填)"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="backReasonVisible = false">取消</el-button>
<el-button type="primary" @click="confirmCancel">确定退回</el-button>
</template>
</el-dialog>
</template>
<script setup>
import {ref, computed, getCurrentInstance} from 'vue';
@@ -238,6 +257,9 @@ const activeNames = ref([]);
const prescriptionList = ref([]);
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
const type = ref(null);
const backReasonVisible = ref(false);
const backReasonForm = ref({ reason: '' });
const backReasonFormRef = ref(null);
const { proxy } = getCurrentInstance();
const loading = ref(false);
const chooseAll = ref(false);
@@ -444,18 +466,35 @@ function handleCancel() {
proxy.$message.error('该药品已由药房发放,请先执行退药处理,不可直接退回');
return;
}
cancel(list).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess(res.msg);
handleGetPrescription();
}
});
console.log(list, 'list');
// 显示退回原因弹窗
backReasonForm.value.reason = '';
backReasonVisible.value = true;
} else {
proxy.$message.warning('请先选择医嘱信息');
}
}
/** 确定退回 — 从弹窗获取原因后调用API */
function confirmCancel() {
if (!backReasonForm.value.reason.trim()) {
proxy.$message.warning('请输入退回原因');
return;
}
let list = getSelectRows();
// 将退回原因附加到每个项目
let requestList = list.map(item => ({
...item,
backReason: backReasonForm.value.reason.trim()
}));
cancel(requestList).then((res) => {
if (res.code == 200) {
proxy.$modal.msgSuccess(res.msg);
handleGetPrescription();
}
});
backReasonVisible.value = false;
}
function getSelectRows() {
// 获取选中的医嘱信息
let list = [];