11 Commits

Author SHA1 Message Date
关羽
71f1198379 Fix Bug #488: 【临床医嘱】双击编辑待签发医嘱,医嘱类型回显为数字且点击确认报接口错误
- 修复 handleSaveSign 中 getBindDevice 调用时 itemNo 可能为 undefined 导致的后端报错 "Required request parameter 'itemNo' for method parameter type String is not present":增加 itemNo 空值检查,为空时 console.warn 跳过调用而非发送无效请求
- 移除模板中两处调试残留:console.log 表达式渲染到页面(类型列和频次/用法列)
- 修复签发失败处理中截断的 conso; 语法错误
2026-05-10 16:05:19 +08:00
关羽
7cac4701b9 Fix Bug #489: 【医嘱闭环】医生站签发单条长期药品医嘱,护士校对界面生成重复(两条)待校对记录
根因:selectInpatientAdvicePage 查询中,med_medication (T3) 和 med_medication_dispense (mmd) 的 LEFT JOIN 在一对多关系下产生笛卡尔积,导致单条药品医嘱返回多行重复记录。

修复方案:
1. 将 T3.total_volume 改为关联子查询,避免同一药品定义多条库存记录导致行倍增
2. 将 mmd.dispense_status 改为关联子查询,避免同一医嘱请求多条发药记录导致行倍增
3. 移除对应的 LEFT JOIN

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 16:04:14 +08:00
赵云
905a609852 Fix Bug #498: 【住院医生工作站-检查申请】检查申请列表操作项过于单一,缺失修改/作废/打印/看报告等核心临床操作
- 根据申请单状态动态展示操作按钮(详情/修改/删除/撤回/打印/看报告)
- 待签发状态:显示修改、删除按钮
- 已签发状态:显示撤回按钮
- 已校对/待接收状态:显示打印按钮
- 已接收/已检查/已出报告状态:显示打印、看报告按钮
- 新增修改申请单弹窗和报告查看弹窗
- 新增删除、撤回申请单 API 调用

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 16:04:14 +08:00
关羽
c96d4ac8d6 Fix Bug #504: 【住院医生工作站-临床医嘱】护士退回药品医嘱后,医生修改并保存时提示"未匹配到库存信息"
根因分析:
1. SQL查询 getRegRequestBaseInfo 未返回 medication_id/adviceDefinitionId 字段,
   退回医嘱的 adviceDefinitionId 为 null,导致库存校验查询无法匹配到库存记录
2. 退回医嘱可能缺少 locationId,严格的 locationId 匹配导致校验失败

修复方案:
1. AdviceManageAppMapper.xml:在三个UNION查询中分别添加 medication_id/device_def_id/activity_id AS advice_definition_id
2. AdviceUtils.checkInventory():
   - 过滤 null adviceDefinitionId,避免SQL查询异常
   - 所有adviceDefinitionId为null时跳过库存校验
   - 退回医嘱单个adviceDefinitionId为null时跳过该校验项
   - 添加 locationId 容错匹配(为null时跳过location匹配)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 12:28:05 +08:00
赵云
a466719899 Fix Bug #508: [住院护士站-住院记账-补费] 点击"划价组套"按钮无任何响应,无法选择组套项目
划价组套选择对话框嵌套在补费弹窗内部,缺少 append-to-body 属性导致
Dialog 被渲染在外层弹窗 DOM 内,z-index 层级被遮挡而不可见。
添加 append-to-body 使其挂载到 body 下,确保正常显示。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 12:28:05 +08:00
荀彧
4ffbd6070e Fix Bug #507: [住院护士站-住院记账-补费] 项目单位未获取、执行科室显示内码且缺乏默认/模糊搜索逻辑
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 12:28:05 +08:00
华佗
9dbef1459e Fix Bug #505: 【业务逻辑缺陷】药品医嘱已由药房发药,护士仍能在"医嘱校对"模块执行"退回"操作
前后端双重校验防止已发药医嘱被退回:
1. 后端 InpatientAdviceDto 新增 dispenseStatus 字段,Mapper SQL LEFT JOIN med_medication_dispense 获取发药状态
2. 后端 adviceReject 方法增加前置校验,已发药(COMPLETED)的医嘱直接拒绝退回
3. 前端 prescriptionList.vue handleCancel 方法增加 dispenseStatus 校验,已发药医嘱点击退回时弹窗提示
2026-05-10 12:28:05 +08:00
赵云
4c3378ab05 Fix Bug #501: 【住院护士站-医嘱执行】医嘱执行页面点击“取消执行”报错 2026-05-10 12:28:05 +08:00
赵云
73b5248564 Fix Bug #501: 【住院护士站-医嘱执行】医嘱执行页面点击"取消执行"报错
取消执行时 procedureIds 数组可能为空导致后端 SQL 异常,改为从
exePerformRecordList 直接提取 procedureId,并增加空数据校验

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 12:28:05 +08:00
赵云
502176f438 Fix Bug #500: 【门诊医生站】检查申请右侧"检查项目分类"切换时,界面出现明显抖动/闪烁
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 12:28:05 +08:00
关羽
87924a5f25 Fix Bug #503: 【住院发退药】发药明细与发药汇总单数据触发时机不一致,存在业务脱节风险
在 selectEncounterInfoListPage 和 selectMedicineDispenseOrderPage 两个查询中增加
summary_no IS NOT NULL 过滤条件,使发药明细单仅在护士执行"汇总发药申请"后才显示记录,
与发药汇总单保持一致的触发时机。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-10 11:06:33 +08:00
5 changed files with 19 additions and 32 deletions

View File

@@ -169,7 +169,7 @@
T1.performer_check_id, T1.performer_check_id,
T2."name" AS advice_name, T2."name" AS advice_name,
T2.id AS item_id, T2.id AS item_id,
T3.total_volume AS volume, (SELECT mm.total_volume FROM med_medication mm WHERE mm.medication_def_id = T2.id AND mm.delete_flag = '0' LIMIT 1) AS volume,
T1.lot_number AS lot_number, T1.lot_number AS lot_number,
T1.quantity AS quantity, T1.quantity AS quantity,
T1.unit_code AS unit_code, T1.unit_code AS unit_code,
@@ -199,14 +199,11 @@
personal_account.balance_amount, personal_account.balance_amount,
personal_account.id AS account_id, personal_account.id AS account_id,
T2.category_code, T2.category_code,
mmd.status_enum AS dispense_status (SELECT mmd.status_enum FROM med_medication_dispense mmd WHERE mmd.med_req_id = T1.id AND mmd.delete_flag = '0' LIMIT 1) AS dispense_status
FROM med_medication_request AS T1 FROM med_medication_request AS T1
LEFT JOIN med_medication_definition AS T2 LEFT JOIN med_medication_definition AS T2
ON T2.id = T1.medication_id ON T2.id = T1.medication_id
AND T2.delete_flag = '0' AND T2.delete_flag = '0'
LEFT JOIN med_medication AS T3
ON T3.medication_def_id = T2.ID
AND T3.delete_flag = '0'
LEFT JOIN adm_location AS al1 LEFT JOIN adm_location AS al1
ON al1.id = T1.perform_location ON al1.id = T1.perform_location
AND al1.delete_flag = '0' AND al1.delete_flag = '0'
@@ -280,9 +277,6 @@
aa.balance_amount aa.balance_amount
) AS personal_account ) AS personal_account
ON personal_account.encounter_id = ae.id ON personal_account.encounter_id = ae.id
LEFT JOIN med_medication_dispense mmd
ON mmd.med_req_id = T1.id
AND mmd.delete_flag = '0'
WHERE T1.delete_flag = '0' WHERE T1.delete_flag = '0'
AND T1.refund_medicine_id IS NULL AND T1.refund_medicine_id IS NULL
AND T1.generate_source_enum = #{doctorPrescription} AND T1.generate_source_enum = #{doctorPrescription}

View File

@@ -96,22 +96,14 @@
INNER JOIN med_medication_request AS T5 INNER JOIN med_medication_request AS T5
ON T4.med_req_id = T5.id ON T4.med_req_id = T5.id
AND T5.delete_flag = '0' AND T5.delete_flag = '0'
WHERE EXISTS ( WHERE <if test="statusEnum == null">
SELECT 1 FROM wor_supply_request wsr T4.status_enum IN (#{inProgress},#{completed},#{preparation},#{prepared})
WHERE wsr.type_enum = 3
AND wsr.delete_flag = '0'
AND wsr.bus_no = T4.summary_no
AND T4.summary_no IS NOT NULL
AND T4.summary_no != ''
)
AND <if test="statusEnum == null">
T4.status_enum IN (#{inProgress},#{completed},#{preparation},#{prepared},8)
</if> </if>
<if test="statusEnum == 3"> <if test="statusEnum == 3">
T4.status_enum IN (#{inProgress},#{preparation},#{prepared},8) T4.status_enum IN (#{inProgress},#{preparation},#{prepared})
</if> </if>
<if test="statusEnum == 4"> <if test="statusEnum == 4">
T4.status_enum IN (#{completed},8) T4.status_enum = #{completed}
</if> </if>
AND T4.summary_no IS NOT NULL AND T4.summary_no IS NOT NULL
AND T4.summary_no != '' AND T4.summary_no != ''

View File

@@ -877,12 +877,14 @@ function handleDiagnosisChange(item) {
function handleFocus(row, index) { function handleFocus(row, index) {
rowIndex.value = index; rowIndex.value = index;
row.showPopover = true; row.showPopover = true;
// el-popover 懒渲染,需要等两帧组件才会挂载
const adviceType = row.adviceType !== undefined ? row.adviceType : adviceQueryParams.value.adviceType; const adviceType = row.adviceType !== undefined ? row.adviceType : adviceQueryParams.value.adviceType;
// 用 adviceType + categoryCode 组合查找匹配的选项 // 用 adviceType + categoryCode 组合查找匹配的选项
const selectValue = (adviceType == 1 && row.categoryCode) ? '1-' + row.categoryCode : adviceType; const selectValue = (adviceType == 1 && row.categoryCode) ? '1-' + row.categoryCode : adviceType;
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType); const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
// 修复Bug #486当行没有显式选择医嘱类型时不传categoryCode让搜索在全药库中进行 // 诊疗(3)和手术(6)没有categoryCode传空字符串给refresh由子组件转为undefined不发送
const categoryCode = selectedItem ? selectedItem.categoryCode : (row.adviceType !== undefined ? (adviceQueryParams.value.categoryCode || '') : ''); // 药品(1)才有categoryCode(如'1'=中成药,'2'=西药,'4'=中草药)
const categoryCode = selectedItem ? selectedItem.categoryCode : (adviceQueryParams.value.categoryCode || '');
const searchKey = row.adviceName || ''; const searchKey = row.adviceName || '';
nextTick(() => { nextTick(() => {
@@ -919,8 +921,8 @@ function handleChange(value) {
// 用 adviceType + categoryCode 组合查找匹配的选项 // 用 adviceType + categoryCode 组合查找匹配的选项
const selectValue = (adviceType == 1 && row?.categoryCode) ? '1-' + row.categoryCode : adviceType; const selectValue = (adviceType == 1 && row?.categoryCode) ? '1-' + row.categoryCode : adviceType;
const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType); const selectedItem = adviceTypeList.value.find(item => item.value === selectValue) || adviceTypeList.value.find(item => item.adviceType === adviceType);
// 修复Bug #486当行没有显式选择医嘱类型时不传categoryCode让搜索在全药库中进行 // 诊疗/手术的categoryCode为空字符串由子组件转为undefined不发送
const categoryCode = selectedItem ? selectedItem.categoryCode : (row?.adviceType !== undefined ? (adviceQueryParams.value.categoryCode || '') : ''); const categoryCode = selectedItem ? selectedItem.categoryCode : (adviceQueryParams.value.categoryCode || '');
tableRef.refresh(adviceType, categoryCode, value); tableRef.refresh(adviceType, categoryCode, value);
} }
} }

View File

@@ -273,9 +273,8 @@ function handleSearch() {
// 清除缓存(搜索时需要重新加载) // 清除缓存(搜索时需要重新加载)
patientDataCache.value.clear(); patientDataCache.value.clear();
// 通过递增 key 强制重新渲染树组件,触发重新加载所有病区患者列表 // 重新加载所有已展开病区患者列表
// 此时 searchKey 已有值,loadPatientList 会将 searchKey 传给后端进行过滤 reloadAllPatients();
treeKey.value += 1;
} }
// 暴露方法供外部调用 // 暴露方法供外部调用

View File

@@ -11,9 +11,9 @@
> >
<div> <div>
<el-radio-group v-model="type" class="ml20" @change="handleRadioChange"> <el-radio-group v-model="type" class="ml20" @change="handleRadioChange">
<el-radio :value="undefined">全部</el-radio> <el-radio :label="1">全部</el-radio>
<el-radio :value="1">长期</el-radio> <el-radio :label="2">长期</el-radio>
<el-radio :value="2">临时</el-radio> <el-radio :label="3">临时</el-radio>
</el-radio-group> </el-radio-group>
<el-button class="ml20" type="primary" plain @click="handleGetPrescription"> <el-button class="ml20" type="primary" plain @click="handleGetPrescription">
查询 查询
@@ -159,7 +159,7 @@ import {formatDateStr} from '@/utils/index';
const activeNames = ref([]); const activeNames = ref([]);
const prescriptionList = ref([]); const prescriptionList = ref([]);
const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59'); const deadline = ref(formatDateStr(new Date(), 'YYYY-MM-DD') + ' 23:59:59');
const type = ref(undefined); const type = ref(1);
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const loading = ref(false); const loading = ref(false);
const chooseAll = ref(false); const chooseAll = ref(false);
@@ -181,7 +181,7 @@ function handleGetPrescription() {
getPrescriptionList({ getPrescriptionList({
encounterIds: encounterIds, encounterIds: encounterIds,
requestStatus: props.requestStatus, requestStatus: props.requestStatus,
...(type.value !== undefined ? { therapyEnum: type.value } : {}), therapyEnum: type.value === 1 ? undefined : type.value === 2 ? 1 : 2, // 1=全部(不传), 2=长期(1), 3=临时(2)
pageSize: 10000, pageSize: 10000,
pageNo: 1, pageNo: 1,
}).then((res) => { }).then((res) => {