Compare commits

...

3 Commits

Author SHA1 Message Date
750efffa8b fix(#670): 中医处方煎药方式下拉框数据为空 — 添加 method_of_decocting_medicine 字典加载 2026-06-10 23:54:44 +08:00
fa23375050 fix(#718): 停嘱流程优化 — 医嘱状态流转与护士站同步
- AdviceProcessAppServiceImpl: 停嘱逻辑增加护士确认环节
- AdviceManageAppServiceImpl: 医嘱状态查询优化
- RequestStatus: 增加停嘱待确认状态枚举
- medicalConstants: 前端状态常量同步
- OrderForm/prescriptionList: 前端展示优化

由 AI Agent (zhaoyun) 自动修复
2026-06-10 09:00:03 +08:00
8164cec57a fix(#719): 频次/用法和停嘱医生字段为空
根因1: frequencyUsage 由 DictAspect 延迟翻译导致 _dictText 为空
- 改用 DictUtils.getDictLabel 直接翻译,避免 AOP 时序问题

根因2: AdviceProcessAppMapper.xml UNION 分支硬编码 NULL AS stopper_name
- 改为读取 T1.update_by

相关修复: 多个前端组件和后端 mapper 改进

由 AI Agent (zhaoyun) 自动修复
2026-06-10 08:31:37 +08:00
16 changed files with 233 additions and 92 deletions

View File

@@ -186,13 +186,18 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
QueryWrapper<InpatientAdviceParam> queryWrapper
= HisQueryUtils.buildQueryWrapper(inpatientAdviceParam, null, null, null);
// 手动拼接requestStatus条件COMPLETED(3)时同时包含CHECK_VERIFIED(10)和PENDING_RECEIVE(11)
// 手动拼接requestStatus条件
// COMPLETED(3)时同时包含CHECK_VERIFIED(10)和PENDING_RECEIVE(11)
// ACTIVE(2)时同时包含PENDING_STOP(13),以便护士核对停嘱医嘱
// UNION查询外层列名为request_statusT1.status_enum AS request_status不是status_enum
if (requestStatus != null) {
if (RequestStatus.COMPLETED.getValue().equals(requestStatus)) {
queryWrapper.in("request_status",
RequestStatus.COMPLETED.getValue(), RequestStatus.CHECK_VERIFIED.getValue(),
RequestStatus.PENDING_RECEIVE.getValue());
} else if (RequestStatus.ACTIVE.getValue().equals(requestStatus)) {
queryWrapper.in("request_status",
RequestStatus.ACTIVE.getValue(), RequestStatus.PENDING_STOP.getValue());
} else {
queryWrapper.eq("request_status", requestStatus);
}
@@ -251,14 +256,16 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
e.setTotalAmount(e.getQuantity() + unitStr);
}
// 频次/用法组合
// 频次/用法组合直接使用DictUtils翻译避免DictAspect延迟导致_dictText为空
String rateLabel = e.getRateCode() != null ? DictUtils.getDictLabel("rate_code", e.getRateCode()) : null;
String methodLabel = e.getMethodCode() != null ? DictUtils.getDictLabel("method_code", e.getMethodCode()) : null;
StringBuilder freqBuilder = new StringBuilder();
if (e.getRateCode_dictText() != null && !e.getRateCode_dictText().isEmpty()) {
freqBuilder.append(e.getRateCode_dictText());
if (rateLabel != null && !rateLabel.isEmpty()) {
freqBuilder.append(rateLabel);
}
if (e.getMethodCode_dictText() != null && !e.getMethodCode_dictText().isEmpty()) {
if (methodLabel != null && !methodLabel.isEmpty()) {
if (freqBuilder.length() > 0) freqBuilder.append(" ");
freqBuilder.append(e.getMethodCode_dictText());
freqBuilder.append(methodLabel);
}
e.setFrequencyUsage(freqBuilder.length() > 0 ? freqBuilder.toString() : null);
@@ -395,10 +402,29 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
List<Long> serviceReqIds = serviceRequestList.stream().map(PerformInfoDto::getRequestId).toList();
// 先查询服务请求,按 categoryEnum 分流:检查类(23)走 CHECK_VERIFIED其余走 COMPLETED
List<ServiceRequest> allServiceRequests = serviceRequestService.listByIds(serviceReqIds);
List<Long> checkReqIds = allServiceRequests.stream()
// 分离已停嘱(PENDING_STOP)的订单,护士核对后变为已停止(STOPPED)
List<ServiceRequest> pendingStopRequests = allServiceRequests.stream()
.filter(sr -> RequestStatus.PENDING_STOP.getValue().equals(sr.getStatusEnum()))
.toList();
List<ServiceRequest> normalRequests = allServiceRequests.stream()
.filter(sr -> !RequestStatus.PENDING_STOP.getValue().equals(sr.getStatusEnum()))
.toList();
// 已停嘱订单 → 已停止(STOPPED)
if (!pendingStopRequests.isEmpty()) {
List<Long> pendingStopIds = pendingStopRequests.stream().map(ServiceRequest::getId).toList();
serviceRequestService.update(new LambdaUpdateWrapper<ServiceRequest>()
.in(ServiceRequest::getId, pendingStopIds)
.set(ServiceRequest::getStatusEnum, RequestStatus.STOPPED.getValue())
.set(ServiceRequest::getUpdateBy, SecurityUtils.getNickName()));
}
// 正常订单:检查类 → 已校对CHECK_VERIFIED=10其余 → 已完成COMPLETED=3
List<Long> checkReqIds = normalRequests.stream()
.filter(sr -> ActivityDefCategory.TEST.getValue().equals(sr.getCategoryEnum()))
.map(ServiceRequest::getId).toList();
List<Long> otherReqIds = allServiceRequests.stream()
List<Long> otherReqIds = normalRequests.stream()
.filter(sr -> !ActivityDefCategory.TEST.getValue().equals(sr.getCategoryEnum()))
.map(ServiceRequest::getId).toList();
// 检查类 → 已校对CHECK_VERIFIED=10
@@ -410,7 +436,7 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
serviceRequestService.updateCompleteRequestStatus(otherReqIds, practitionerId, checkDate);
}
// 处理转科/出院等特殊医嘱
for (ServiceRequest serviceRequest : allServiceRequests) {
for (ServiceRequest serviceRequest : normalRequests) {
if (ActivityDefCategory.TRANSFER.getValue().equals(serviceRequest.getCategoryEnum())) {
encounterService.updateEncounterStatus(serviceRequest.getEncounterId(),
EncounterZyStatus.PENDING_TRANSFER.getValue());
@@ -421,9 +447,30 @@ public class AdviceProcessAppServiceImpl implements IAdviceProcessAppService {
}
}
if (!medRequestList.isEmpty()) {
// 更新药品请求状态已完成
medicationRequestService.updateCompletedStatusBatch(
medRequestList.stream().map(PerformInfoDto::getRequestId).toList(), practitionerId, checkDate);
List<Long> medReqIds = medRequestList.stream().map(PerformInfoDto::getRequestId).toList();
// 查询药品请求,分离已停嘱(PENDING_STOP)的订单
List<MedicationRequest> allMedRequests = medicationRequestService.list(
new LambdaQueryWrapper<MedicationRequest>()
.select(MedicationRequest::getId, MedicationRequest::getStatusEnum)
.in(MedicationRequest::getId, medReqIds));
List<Long> pendingStopMedIds = allMedRequests.stream()
.filter(mr -> RequestStatus.PENDING_STOP.getValue().equals(mr.getStatusEnum()))
.map(MedicationRequest::getId).toList();
List<Long> normalMedIds = allMedRequests.stream()
.filter(mr -> !RequestStatus.PENDING_STOP.getValue().equals(mr.getStatusEnum()))
.map(MedicationRequest::getId).toList();
// 已停嘱订单 → 已停止(STOPPED)
if (!pendingStopMedIds.isEmpty()) {
medicationRequestService.update(new LambdaUpdateWrapper<MedicationRequest>()
.in(MedicationRequest::getId, pendingStopMedIds)
.set(MedicationRequest::getStatusEnum, RequestStatus.STOPPED.getValue())
.set(MedicationRequest::getUpdateBy, SecurityUtils.getNickName()));
}
// 正常订单 → 已完成(COMPLETED)
if (!normalMedIds.isEmpty()) {
medicationRequestService.updateCompletedStatusBatch(normalMedIds, practitionerId, checkDate);
}
}
return R.ok(null, "校对成功");
}

View File

@@ -190,8 +190,9 @@ public class MedicineSummaryAppServiceImpl implements IMedicineSummaryAppService
}
// 领药人
Long receiverId = medicineSummaryParamList.get(0).getReceiverId();
// 申请时间
Date now = DateUtils.getNowDate();
// 申请时间(优先使用前端传递的操作时间,确保与实际操作时间一致)
Date now = medicineSummaryParamList.get(0).getDispenseTime() != null
? medicineSummaryParamList.get(0).getDispenseTime() : DateUtils.getNowDate();
// 申请人
Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
// 药品发放id

View File

@@ -1122,14 +1122,14 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
iMedicationRequestService.update(new LambdaUpdateWrapper<MedicationRequest>()
.in(MedicationRequest::getId, medicineRequestIds)
.set(MedicationRequest::getEffectiveDoseEnd, stopTime)
.set(MedicationRequest::getStatusEnum, RequestStatus.STOPPED.getValue())
.set(MedicationRequest::getStatusEnum, RequestStatus.PENDING_STOP.getValue())
.set(MedicationRequest::getUpdateBy, stopUserName));
}
if (!activityRequestIds.isEmpty()) {
iServiceRequestService.update(new LambdaUpdateWrapper<ServiceRequest>()
.in(ServiceRequest::getId, activityRequestIds)
.set(ServiceRequest::getOccurrenceEndTime, stopTime)
.set(ServiceRequest::getStatusEnum, RequestStatus.STOPPED.getValue())
.set(ServiceRequest::getStatusEnum, RequestStatus.PENDING_STOP.getValue())
.set(ServiceRequest::getUpdateBy, stopUserName));
}
return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[]{"医嘱停止"}));
@@ -1173,7 +1173,8 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
.select(MedicationRequest::getId, MedicationRequest::getStatusEnum)
.in(MedicationRequest::getId, medicineRequestIds));
for (MedicationRequest mr : medicineRequestList) {
if (!RequestStatus.STOPPED.getValue().equals(mr.getStatusEnum())) {
if (!RequestStatus.STOPPED.getValue().equals(mr.getStatusEnum())
&& !RequestStatus.PENDING_STOP.getValue().equals(mr.getStatusEnum())) {
throw new ServiceException("护士站已确认停止该医嘱,无法取消停嘱!");
}
}
@@ -1184,7 +1185,8 @@ public class AdviceManageAppServiceImpl implements IAdviceManageAppService {
.select(ServiceRequest::getId, ServiceRequest::getStatusEnum)
.in(ServiceRequest::getId, activityRequestIds));
for (ServiceRequest sr : activityRequestList) {
if (!RequestStatus.STOPPED.getValue().equals(sr.getStatusEnum())) {
if (!RequestStatus.STOPPED.getValue().equals(sr.getStatusEnum())
&& !RequestStatus.PENDING_STOP.getValue().equals(sr.getStatusEnum())) {
throw new ServiceException("护士站已确认停止该医嘱,无法取消停嘱!");
}
}

View File

@@ -207,7 +207,7 @@
NULL::numeric AS unit_price,
NULL::numeric AS total_price,
NULL::bigint AS stopper_id,
NULL::varchar AS stopper_name
T1.update_by AS stopper_name
FROM med_medication_request AS T1
LEFT JOIN med_medication_definition AS T2
ON T2.id = T1.medication_id
@@ -353,7 +353,7 @@
NULL::numeric AS unit_price,
NULL::numeric AS total_price,
NULL::bigint AS stopper_id,
NULL::varchar AS stopper_name
T1.update_by AS stopper_name
FROM wor_service_request AS T1
LEFT JOIN wor_activity_definition AS T2
ON T2.id = T1.activity_id

View File

@@ -189,6 +189,7 @@
T1.id AS request_id,
T1.id || '-1' AS unique_key,
T1.practitioner_id AS requester_id,
ap.name AS requester_id_dict_text,
T1.create_time AS request_time,
CASE WHEN T1.practitioner_id = #{practitionerId} THEN '1' ELSE '0' END AS biz_request_flag,
T1.content_json AS content_json,
@@ -223,6 +224,7 @@
T1.effective_dose_end AS stop_time,
T1.update_by AS stop_user_name
FROM med_medication_request AS T1
LEFT JOIN adm_practitioner AS ap ON ap.id = T1.practitioner_id AND ap.delete_flag = '0'
LEFT JOIN med_medication_definition AS T2 ON T2.ID = T1.medication_id
AND T2.delete_flag = '0'
LEFT JOIN med_medication AS T3 ON T3.medication_def_id = T2.ID
@@ -246,6 +248,7 @@
T1.id AS request_id,
T1.id || '-2' AS unique_key,
T1.requester_id AS requester_id,
ap.name AS requester_id_dict_text,
T1.create_time AS request_time,
CASE WHEN T1.requester_id = #{practitionerId} THEN '1' ELSE '0' END AS biz_request_flag,
T1.content_json AS content_json,
@@ -280,6 +283,7 @@
NULL::timestamp AS stop_time,
'' AS stop_user_name
FROM wor_device_request AS T1
LEFT JOIN adm_practitioner AS ap ON ap.id = T1.requester_id AND ap.delete_flag = '0'
LEFT JOIN adm_device_definition AS T2 ON T2.ID = T1.device_def_id
AND T2.delete_flag = '0'
LEFT JOIN adm_charge_item AS T3
@@ -300,6 +304,7 @@
T1.id AS request_id,
T1.id || '-3' AS unique_key,
T1.requester_id AS requester_id,
ap.name AS requester_id_dict_text,
T1.create_time AS request_time,
CASE WHEN T1.requester_id = #{practitionerId} THEN '1' ELSE '0' END AS biz_request_flag,
T1.content_json AS content_json,
@@ -334,6 +339,7 @@
T1.occurrence_end_time AS stop_time,
T1.update_by AS stop_user_name
FROM wor_service_request AS T1
LEFT JOIN adm_practitioner AS ap ON ap.id = T1.requester_id AND ap.delete_flag = '0'
LEFT JOIN wor_activity_definition AS T2
ON T2.ID = T1.activity_id
AND T2.delete_flag = '0'

View File

@@ -74,6 +74,11 @@ public enum RequestStatus implements HisEnumInterface {
*/
CHECK_RECEIVED(12, "check_received", "已接收"),
/**
* 已停嘱(医生停嘱,等待护士核对)
*/
PENDING_STOP(13, "pending_stop", "已停嘱"),
/**
* 已完成(药品发药完成)
*/

View File

@@ -40,6 +40,8 @@ export const RequestStatus = {
PENDING_RECEIVE: 11,
/** 已接收(检查申请:医技科室已接单) */
CHECK_RECEIVED: 12,
/** 已停嘱(医生停嘱,等待护士核对) */
PENDING_STOP: 13,
/** 已完成(药品发药完成) */
DISPENSE_COMPLETED: 20,
};
@@ -59,6 +61,7 @@ export const RequestStatusDescriptions = {
10: '已校对',
11: '待接收',
12: '已接收',
13: '已停嘱',
20: '已完成',
};

View File

@@ -92,6 +92,7 @@
placeholder="请选"
class="inline-select"
:disabled="!isEditMode"
clearable
>
<el-option
v-for="doctor in getDoctorOptions(filterParams.appointmentType)"
@@ -113,6 +114,7 @@
placeholder="请选"
class="inline-select"
:disabled="!isEditMode"
clearable
>
<el-option
label="诊室1"
@@ -206,6 +208,7 @@
placeholder="请选"
class="inline-select"
:disabled="!isEditMode"
clearable
@change="handleAppointmentItemChange(scope.row)"
>
<el-option
@@ -247,6 +250,7 @@
placeholder="请选择诊查项目"
class="inline-select"
:disabled="!isEditMode"
clearable
@change="handleClinicItemChange(scope.row)"
>
<el-option

View File

@@ -1,4 +1,4 @@
<template>
<template>
<div class="appoinmentmanage-wrapper">
<div class="appoinmentmanage-container">
<div class="appoinmentmanage-header">
@@ -335,6 +335,7 @@
v-model="scope.row.doctorId"
placeholder="请选"
class="inline-select"
clearable
:disabled="!isEditMode"
@change="(selectedId) => handleDoctorChange(selectedId, scope.row)"
>
@@ -359,6 +360,7 @@
filterable
:remote-method="searchClinicRooms"
class="inline-select"
clearable
:disabled="!isEditMode"
>
<el-option
@@ -443,6 +445,7 @@
v-model="scope.row.appointmentItem"
placeholder="请选"
class="inline-select"
clearable
:disabled="!isEditMode"
@change="handleAppointmentItemChange(scope.row)"
>
@@ -474,6 +477,7 @@
v-model="scope.row.clinicItem"
placeholder="请选择诊查项目"
class="inline-select"
clearable
:disabled="!isEditMode"
@change="handleClinicItemChange(scope.row)"
>

View File

@@ -1738,7 +1738,7 @@ const loadCategoryItems = async (categoryKey, loadMore = false) => {
const mappedItems = records.map(item => {
// 套餐项目处理:需同时满足 feePackageId 有效且 packageName 非空
// 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
? (parseFloat(item.packageAmount || 0) || parseFloat(item.retailPrice || 0) || parseFloat(item.price || 0))
: (parseFloat(item.retailPrice || 0) || parseFloat(item.price || 0))
@@ -2226,7 +2226,7 @@ const handleSave = () => {
// Bug #326修复: 传入 activityId后端直接使用 ID 关联,避免用名称反查
activityId: item.activityId || item.itemId || null,
feePackageId: item.feePackageId || null,
isPackage: item.isPackage || false,
isPackage: Boolean(item.isPackage),
sampleType: item.sampleType || '',
unit: item.unit || ''
}))

View File

@@ -636,13 +636,14 @@ const inputRefs = ref({}); // 存储输入框实例
const requiredProps = ref([]); // 存储必填项 prop 顺序
const totalAmount = ref(0);
const tcmDianosis = ref();
const { method_code, unit_code, rate_code, distribution_category_code, dosage_instruction } =
const { method_code, unit_code, rate_code, distribution_category_code, dosage_instruction, method_of_decocting_medicine } =
proxy.useDict(
'method_code',
'unit_code',
'rate_code',
'distribution_category_code',
'dosage_instruction'
'dosage_instruction',
'method_of_decocting_medicine'
);
onMounted(() => {

View File

@@ -198,11 +198,23 @@
align="center"
min-width="100"
/>
<!-- <vxe-column title="操作" min-width="100" align="center" fixed="right">
<vxe-column
title="操作"
min-width="100"
align="center"
fixed="right"
>
<template #default="scope">
<el-button link type="primary" size="small">补打</el-button>
<el-button
link
type="primary"
size="small"
@click="handlePrint(scope.row)"
>
打印
</el-button>
</template>
</vxe-column> -->
</vxe-column>
</vxe-table>
<pagination
v-show="total > 0"
@@ -238,6 +250,7 @@
<script setup>
import {nextTick, ref} from 'vue';
import {simplePrint, PRINT_TEMPLATE} from '@/utils/printUtils';
import {getDepositInfo, getDepositInfoPage} from './components/api';
import PatientList from './components/patientList.vue';
import ChargeDialog from './components/chargeDialog.vue';
@@ -319,6 +332,36 @@ function refund() {
}
}
/**
* 打印预交金收据
*
* @param {Object} row 当前行数据
*/
async function handlePrint(row) {
if (!patientInfo.value.patientId) {
proxy.$modal.msgError("请先选择病人!");
return;
}
try {
const printData = {
patientName: patientInfo.value.patientName || "",
encounterNosd: patientInfo.value.busNo || "",
inHospitalOrgName: patientInfo.value.inHospitalOrgName || "",
patientId: patientInfo.value.patientId || "",
contractName: patientInfo.value.contractName || "",
currentTime: row.operateTime || new Date().toLocaleString(),
balanceAmount: row.tenderedAmount ? row.tenderedAmount.toFixed(2) : "0.00",
amountInWords: "",
paymentDetails: "收据号: " + (row.paymentNo || ""),
};
await simplePrint(PRINT_TEMPLATE.ADVANCE_PAYMENT, printData);
proxy.$modal.msgSuccess("打印成功");
} catch (error) {
console.error("预交金打印失败:", error);
proxy.$modal.msgError("打印失败: " + (error.message || "未知错误"));
}
}
/** 选择病人 */
function handlePatientSelected(row) {
// console.log(row, 'rowwwwwwwwhandlePatientSelected');

View File

@@ -1,4 +1,4 @@
<template>
<template>
<el-form :model="row" :rules="rules" :ref="(el) => (formRef = el)" :label-width="100">
<div class="expend_div" style="padding: 16px; background: #f8f9fa; border-radius: 8px">
<template v-if="row.adviceType == 1">
@@ -477,7 +477,7 @@
</el-form-item>
<div class="form-group">
<el-select
v-model="row.lotNumber"
v-model="row.inventoryId"
style="width: 180px; margin-right: 20px"
placeholder="药房"
>

View File

@@ -1,4 +1,4 @@
<template>
<template>
<div class="inpatientDoctor-order-container" style="width: 100%">
<div style="margin-bottom: 5px" class="order-operate-btn">
<div style="height: 44px; display: flex; align-items: center; flex: none">
@@ -268,6 +268,7 @@
<el-tag v-else-if="scope.row.statusEnum == 10" type="primary">已校对</el-tag>
<el-tag v-else-if="scope.row.statusEnum == 11" type="primary">待接收</el-tag>
<el-tag v-else-if="scope.row.statusEnum == 3" type="success">已校对</el-tag>
<el-tag v-else-if="scope.row.statusEnum == 13" type="warning">已停嘱</el-tag>
<el-tag v-else-if="scope.row.statusEnum == 6" type="danger">停止</el-tag>
<el-tag v-else-if="scope.row.statusEnum == 20" type="success">已完成</el-tag>
<el-tag v-else type="info">{{ scope.row.chargeStatus_enumText }}</el-tag>
@@ -447,12 +448,13 @@ import {
} from '../api';
import adviceBaseList from '../adviceBaseList';
import {calculateQuantityByDays} from '@/utils/his';
import {localPatientInfo as patientInfo} from '../../store/localPatient.js';
import {localPatientInfo as localPatientInfoRef} from '../../store/localPatient.js';
import OrderGroupDrawer from '@/views/doctorstation/components/prescription/orderGroupDrawer.vue';
import PrescriptionHistory from '@/views/doctorstation/components/prescription/prescriptionHistory.vue';
import Decimal from 'decimal.js';
import {ElMessage, ElMessageBox} from 'element-plus';
import useUserStore from '@/store/modules/user';
import {RequestStatus} from '@/utils/medicalConstants';
import ApplicationFormBottomBtn from './applicationForm/applicationFormBottomBtn.vue';
import LeaveHospitalDialog from './applicationForm/leaveHospitalDialog.vue';
import TransferOrganizationDialog from './applicationForm/transferOrganizationDialog.vue';
@@ -517,10 +519,10 @@ const unitMap = ref({
unit: 'unit',
});
const buttonDisabled = computed(() => {
return !patientInfo.value;
return !localPatientInfoRef.value;
});
const isSaveDisabled = computed(() => {
return !patientInfo.value || prescriptionList.value.length === 0;
return !localPatientInfoRef.value || prescriptionList.value.length === 0;
});
const props = defineProps({
patientInfo: {
@@ -581,9 +583,10 @@ const adviceTypeList = computed(() => {
hasShownPharmacyConfigWarning.value = true;
}
// 只返回不需要取药科室配置的类别(诊疗、手术、出院带药)
// 只返回不需要取药科室配置的类别(诊疗、耗材、手术、出院带药)
return [
{ label: '诊疗', value: 3, adviceType: 3, categoryCode: '' },
{ label: '耗材', value: 2, adviceType: 2, categoryCode: '' },
{ label: '手术', value: 6, adviceType: 6, categoryCode: '' },
{ label: '出院带药', value: 7, adviceType: 7, categoryCode: '' },
{ label: '文字', value: 8, adviceType: 8, categoryCode: '' },
@@ -610,8 +613,9 @@ const adviceTypeList = computed(() => {
typeList.push({ label: '中草药', value: '1-4', adviceType: 1, categoryCode: '4' });
}
// 始终添加诊疗和手术(它们不受取药配置限制)
// 始终添加诊疗、耗材和手术(它们不受取药配置限制)
typeList.push({ label: '诊疗', value: 3, adviceType: 3, categoryCode: '' });
typeList.push({ label: '耗材', value: 2, adviceType: 2, categoryCode: '' });
typeList.push({ label: '手术', value: 6, adviceType: 6, categoryCode: '' });
// 始终添加"出院带药"选项(不需要取药科室配置)
@@ -635,6 +639,10 @@ const statusOption = [
label: '已签发',
value: 2,
},
{
label: '已停嘱',
value: 13,
},
{
label: '停止',
value: 6,
@@ -708,7 +716,7 @@ function getListInfo(addNewRow) {
const orgTreePromise = getOrgTree().then((res) => {
organization.value = res?.data?.records ?? res?.data ?? [];
});
getPrescriptionList(patientInfo.value.encounterId).then((res) => {
getPrescriptionList(localPatientInfoRef.value.encounterId).then((res) => {
// 等待科室树加载完成后再处理处方数据,确保 resolveOrgId 能正确匹配
orgTreePromise.then(() => {
loading.value = false;
@@ -724,6 +732,11 @@ function getListInfo(addNewRow) {
return {
...parsedContent,
...item,
// 🔧 修复:确保开嘱医生名称正确显示
// 优先使用后端返回的 requesterId_dictText其次从 userStore 获取
requesterId_dictText: item.requesterId_dictText || item.requesterId_dict_text
|| (String(item.requesterId) === String(userStore.practitionerId) ? userStore.name : '')
|| parsedContent?.requesterId_dictText || '-',
// 🔧 修复contentJson 中的 totalPrice 优先于 charge_item 表的 totalPrice
// charge_item.totalPrice 可能为 0 或 null新建医嘱时导致总金额显示为 "-"
totalPrice: parsedContent?.totalPrice || item.totalPrice,
@@ -772,10 +785,10 @@ function getListInfo(addNewRow) {
}
});
}).catch(() => { loading.value = false; });
getContract({ encounterId: patientInfo.value.encounterId }).then((res) => {
getContract({ encounterId: localPatientInfoRef.value.encounterId }).then((res) => {
contractList.value = res.data;
});
accountId.value = patientInfo.value.accountId;
accountId.value = localPatientInfoRef.value.accountId;
// 加载已配置的药品类别
loadConfiguredCategories();
@@ -785,7 +798,7 @@ function getListInfo(addNewRow) {
* 加载已配置的药品类别
*/
function loadConfiguredCategories() {
const orgId = patientInfo.value?.inHospitalOrgId;
const orgId = localPatientInfoRef.value?.inHospitalOrgId;
if (!orgId) {
isCategoryLoaded.value = true; // 标记已加载即使没有科室ID
return;
@@ -859,7 +872,7 @@ const filterPrescriptionList = computed(() => {
});
function getDiagnosisInfo() {
getEncounterDiagnosis(patientInfo.value.encounterId).then((res) => {
getEncounterDiagnosis(localPatientInfoRef.value.encounterId).then((res) => {
diagnosisList.value = res.data;
let diagnosisInfo = diagnosisList.value.filter((item) => {
return item.maindiseFlag == 1;
@@ -887,13 +900,14 @@ function getRowSelectValue(row) {
if (row.adviceType == 7) {
return 7;
}
// 耗材(adviceType=2)直接返回数字值,与 adviceTypeList 中的 value 匹配
return row.adviceType;
}
// 新增医嘱
function handleAddPrescription() {
// 校验是否选中患者
if (!patientInfo.value || !patientInfo.value.encounterId) {
if (!localPatientInfoRef.value || !localPatientInfoRef.value.encounterId) {
proxy.$modal.msgWarning('请先选择患者');
return;
}
@@ -942,9 +956,9 @@ function checkUnit(item, row) {
* @returns {boolean} true=通过, false=不通过
*/
function validateStartTime(startTime) {
if (!startTime || !patientInfo.value?.inHospitalTime) return true;
if (!startTime || !localPatientInfoRef.value?.inHospitalTime) return true;
const startDate = new Date(startTime);
const inHospitalDate = new Date(patientInfo.value.inHospitalTime);
const inHospitalDate = new Date(localPatientInfoRef.value.inHospitalTime);
if (startDate < inHospitalDate) {
const pad = (n) => String(n).padStart(2, '0');
const d = inHospitalDate;
@@ -1448,9 +1462,9 @@ function handleSave() {
// 签发处理逻辑
function executeSaveLogic() {
saveList.forEach((item) => {
item.patientId = patientInfo.value.patientId;
item.encounterId = patientInfo.value.encounterId;
item.accountId = patientInfo.value.accountId;
item.patientId = localPatientInfoRef.value.patientId;
item.encounterId = localPatientInfoRef.value.encounterId;
item.accountId = localPatientInfoRef.value.accountId;
item.dbOpType = '1';
// Bug #589: 出院带药保存时转为药品类型
if (item.adviceType == 7) {
@@ -1479,11 +1493,11 @@ function handleSave() {
// 保存签发按钮
isSaving.value = true;
console.log('签发处方参数:', {
organizationId: patientInfo.value.inHospitalOrgId,
organizationId: localPatientInfoRef.value.inHospitalOrgId,
adviceSaveList: list,
});
savePrescriptionSign({
organizationId: patientInfo.value.inHospitalOrgId,
organizationId: localPatientInfoRef.value.inHospitalOrgId,
regAdviceSaveList: list,
})
.then((res) => {
@@ -1545,8 +1559,8 @@ function handleOrderBindInfo(bindIdInfo) {
const newRow = {
...prescriptionList.value[rowIndex.value],
uniqueKey: nextId.value++,
patientId: patientInfo.value.patientId,
encounterId: patientInfo.value.encounterId,
patientId: localPatientInfoRef.value.patientId,
encounterId: localPatientInfoRef.value.encounterId,
accountId: accountId.value,
quantity: item.quantity,
methodCode: item.methodCode,
@@ -1649,8 +1663,8 @@ function handleSaveSign(row, index) {
// 执行保存
row.contentJson = undefined;
row.patientId = patientInfo.value.patientId;
row.encounterId = patientInfo.value.encounterId;
row.patientId = localPatientInfoRef.value.patientId;
row.encounterId = localPatientInfoRef.value.encounterId;
row.accountId = accountId.value;
// 🔧 文字医嘱(type=8)跳过计费逻辑总金额为0
@@ -1898,9 +1912,9 @@ function setValue(row) {
// 2. 诊疗类型优先使用项目维护的所属科室(row.orgId)其次positionId
// 3. 如果都为空,回退到患者当前所在科室(patientInfo.orgId)
// 4. 使用 resolveOrgId 从组织树中匹配正确的 String id解决大 Long 精度丢失问题
orgId: row.adviceType != 3 ? undefined : (resolveOrgId(row.orgId || row.positionId || patientInfo.value?.inHospitalOrgId) || ''),
orgId: row.adviceType != 3 ? undefined : (resolveOrgId(row.orgId || row.positionId || localPatientInfoRef.value?.inHospitalOrgId) || ''),
// 🔧 修复:同时保存 orgName当 orgId 在科室树中匹配不到时作为兜底显示
orgName: row.adviceType != 3 ? undefined : (findOrgName(row.orgId || row.positionId || patientInfo.value?.inHospitalOrgId) || row.orgName || patientInfo.value?.inHospitalOrgName || ''),
orgName: row.adviceType != 3 ? undefined : (findOrgName(row.orgId || row.positionId || localPatientInfoRef.value?.inHospitalOrgId) || row.orgName || localPatientInfoRef.value?.inHospitalOrgName || ''),
// dose: undefined, Removed to preserve dose value from group package
unitCodeList: unitCodeList.value,
doseUnitCode: row.doseUnitCode,
@@ -2004,8 +2018,8 @@ function handleSaveGroup(orderGroupList) {
// 创建新的处方项目
const newRow = {
...prescriptionList.value[tempIndex],
patientId: patientInfo.value.patientId,
encounterId: patientInfo.value.encounterId,
patientId: localPatientInfoRef.value.patientId,
encounterId: localPatientInfoRef.value.encounterId,
accountId: accountId.value,
// 🔧 修复 Bug #403从 mergedDetail 读取明细字段,而非直接从 item 取
// item.dose 等字段可能为 nullmergedDetail 已做 ?? 兜底
@@ -2019,9 +2033,9 @@ function handleSaveGroup(orderGroupList) {
unitCode: mergedDetail.unitCode ?? item.unitCode,
unitCode_dictText: item.unitCodeName || mergedDetail.unitCodeName || '',
statusEnum: 1,
orgId: resolveOrgId(mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || '',
orgId: resolveOrgId(mergedDetail.orgId || localPatientInfoRef.value?.inHospitalOrgId) || '',
// 🔧 修复:同时存储 orgName确保树匹配不到时仍有中文名称可显示
orgName: findOrgName(mergedDetail.orgId || patientInfo.value?.inHospitalOrgId) || mergedDetail.orgName || patientInfo.value?.inHospitalOrgName || '',
orgName: findOrgName(mergedDetail.orgId || localPatientInfoRef.value?.inHospitalOrgId) || mergedDetail.orgName || localPatientInfoRef.value?.inHospitalOrgName || '',
startTime: mergedDetail.startTime || defaultStartTimeFn(),
dbOpType: prescriptionList.value[tempIndex].requestId ? '2' : '1',
conditionId: conditionId.value,
@@ -2063,8 +2077,8 @@ function handleSaveGroup(orderGroupList) {
function handleSaveHistory(value) {
let saveRow = {
...value,
patientId: patientInfo.value.patientId,
encounterId: patientInfo.value.encounterId,
patientId: localPatientInfoRef.value.patientId,
encounterId: localPatientInfoRef.value.encounterId,
accountId: accountId.value,
uniqueKey: undefined,
startTime: defaultStartTimeFn(),
@@ -2226,10 +2240,10 @@ function handleStopAdvice() {
break;
}
}
// 找出停嘱的
// 找出停嘱的(已停止=6 或 已停嘱=13 的不允许再停)
for (let index = 0; index < selectRows.length; index++) {
const item = selectRows[index];
if (item.statusEnum == 6) {
if (item.statusEnum == 6 || item.statusEnum == 13) {
isStop = false;
break;
}
@@ -2288,9 +2302,9 @@ function confirmStopAdvice() {
return;
}
// 校验:停嘱时间不能早于患者入院时间
if (patientInfo.value?.inHospitalTime) {
if (localPatientInfoRef.value?.inHospitalTime) {
const stopDate = new Date(stopForm.stopTime);
const inHospitalDate = new Date(patientInfo.value.inHospitalTime);
const inHospitalDate = new Date(localPatientInfoRef.value.inHospitalTime);
if (stopDate < inHospitalDate) {
const pad = (n) => String(n).padStart(2, '0');
const d = inHospitalDate;
@@ -2333,11 +2347,11 @@ function handleResumeAdvice() {
});
return;
}
// 校验:只有状态为"停止"(statusEnum=6)的医嘱才能恢复
// 校验:只有状态为"停止"(statusEnum=6)或"已停嘱"(statusEnum=13)的医嘱才能恢复
let hasStopOrder = false;
for (let index = 0; index < selectRows.length; index++) {
const item = selectRows[index];
if (item.statusEnum == 6) {
if (item.statusEnum == 6 || item.statusEnum == 13) {
hasStopOrder = true;
break;
}
@@ -2345,7 +2359,7 @@ function handleResumeAdvice() {
if (!hasStopOrder) {
ElMessage({
type: 'error',
message: '请选择已停止的医嘱进行恢复',
message: '请选择已停止或已停嘱的医嘱进行恢复',
});
return;
}
@@ -2353,7 +2367,7 @@ function handleResumeAdvice() {
let allStop = true;
for (let index = 0; index < selectRows.length; index++) {
const item = selectRows[index];
if (item.statusEnum != 6) {
if (item.statusEnum != 6 && item.statusEnum != 13) {
allStop = false;
break;
}
@@ -2361,7 +2375,7 @@ function handleResumeAdvice() {
if (!allStop) {
ElMessage({
type: 'error',
message: '恢复操作只能选择已停止的医嘱,请重新选择',
message: '恢复操作只能选择已停止或已停嘱的医嘱,请重新选择',
});
return;
}
@@ -2407,10 +2421,10 @@ function combination() {
break;
}
}
// 找出停嘱的
// 找出停嘱的(已停止或已停嘱的不允许组合)
for (let index = 0; index < selectRows.length; index++) {
const item = selectRows[index];
if (item.statusEnum == 6) {
if (item.statusEnum == RequestStatus.STOPPED || item.statusEnum == RequestStatus.PENDING_STOP) {
isStop = false;
break;
}
@@ -2507,10 +2521,10 @@ function split() {
break;
}
}
// 找出停嘱的
// 找出停嘱的(已停止或已停嘱的不允许拆组)
for (let index = 0; index < selectRows.length; index++) {
const item = selectRows[index];
if (item.statusEnum == 6) {
if (item.statusEnum == RequestStatus.STOPPED || item.statusEnum == RequestStatus.PENDING_STOP) {
isStop = false;
break;
}
@@ -2805,7 +2819,7 @@ function sortPrescriptionList() {
}
function handleLeaveHospital() {
if (!patientInfo.value) {
if (!localPatientInfoRef.value) {
proxy.$modal.msgWarning('请先选择患者');
return;
}

View File

@@ -359,8 +359,11 @@ function handleMedicineSummary() {
return;
}
let ids = [];
const now = proxy.formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss');
paramList.forEach((item) => {
ids.push(...item.dispenseIds);
item.dispenseIds.forEach((d) => {
ids.push({ ...d, dispenseTime: now });
});
});
if (ids.length === 0) {
proxy.$message.warning('所选药品未关联发放信息');

View File

@@ -1,4 +1,4 @@
<template>
<template>
<div style="height: calc(100vh - 126px); display: flex; flex-direction: column; overflow: hidden">
<div
style="
@@ -16,7 +16,7 @@
v-model="type"
@change="handleRadioChange"
>
<el-radio :value="null">
<el-radio :value="THERAPY_TYPE_ALL">
全部
</el-radio>
<el-radio :value="1">
@@ -26,6 +26,16 @@
临时
</el-radio>
</el-radio-group>
<span style="flex-shrink: 0;">截止时间</span>
<el-date-picker
v-model="deadline"
type="datetime"
format="YYYY-MM-DD HH:mm:ss"
placeholder="选择截止时间"
value-format="YYYY-MM-DD HH:mm:ss"
:clearable="false"
style="width: 200px;"
/>
<el-button
type="primary"
plain
@@ -336,7 +346,8 @@ import {RequestStatus} from '@/utils/medicalConstants';
const activeNames = ref([]);
const prescriptionList = ref([]);
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
const type = ref(null);
const THERAPY_TYPE_ALL = 0;
const type = ref(THERAPY_TYPE_ALL);
const backReasonVisible = ref(false);
const backReasonForm = ref({ reason: '' });
const backReasonFormRef = ref(null);
@@ -391,13 +402,14 @@ const getStatusDisplayText = (row) => {
const getStatusType = (status) => {
const map = {
1: 'info',
2: 'primary',
3: 'success',
4: 'warning',
5: 'danger',
6: 'danger',
7: 'info',
[RequestStatus.DRAFT]: 'info',
[RequestStatus.ACTIVE]: 'primary',
[RequestStatus.COMPLETED]: 'success',
[RequestStatus.ON_HOLD]: 'warning',
[RequestStatus.CANCELLED]: 'danger',
[RequestStatus.PENDING_STOP]: 'warning',
[RequestStatus.STOPPED]: 'danger',
[RequestStatus.ENDED]: 'info',
};
return map[status] || 'info';
};
@@ -435,7 +447,8 @@ function handleGetPrescription() {
getPrescriptionList({
encounterIds: encounterIds,
requestStatus: props.requestStatus,
...(type.value != null ? { therapyEnum: type.value } : {}),
...(type.value !== THERAPY_TYPE_ALL ? { therapyEnum: type.value } : {}),
deadline: deadline.value,
pageSize: 10000,
pageNo: 1,
}).then((res) => {
@@ -455,8 +468,6 @@ function handleGetPrescription() {
// 将分组结果转换为数组形式
prescriptionList.value = Object.values(groupedPrescriptions);
console.log(prescriptionList.value, '1111');
console.log('@@@@@=======>', JSON.stringify(prescriptionList.value));
loading.value = false;
getGroupMarkers();
});
@@ -474,7 +485,6 @@ function getGroupMarkers() {
prescription.groupIcon = null;
});
});
console.log('prescriptionList====>', JSON.stringify(prescriptionList.value));
// 创建一个映射来存储每个 groupId 对应的行索引
const groupMap = {};
@@ -512,7 +522,6 @@ function getGroupMarkers() {
});
}
});
console.log('prescriptionList====>', JSON.stringify(prescriptionList.value));
}
// 选择框改变时的处理
@@ -532,7 +541,6 @@ function handleCheck() {
handleGetPrescription();
}
});
console.log(list, 'list');
} else {
proxy.$message.warning('请先选择医嘱信息');
}