fix(#594): 请修复 Bug #594:【住院医生工作站-临床医嘱】开立需皮试药物时系统未弹出皮试确认框,且医嘱输入行皮试字段置灰只读无法手动编辑

根因:
- **
- 住院医生工作站医嘱录入组件(`index.vue`)的 `selectAdviceBase()` 函数未检查药品的 `skinTestFlag` 字段,选择皮试药品后直接静默填充行数据,未弹出皮试确认弹窗
- 皮试列(`<el-table-column label="皮试">`)仅渲染只读文本 `{{ scope.row.skinTestFlag_enumText || '-' }}`,无任何可编辑组件
- `setValue()`、`getListInfo()`、`handleSaveSign()`、`handleSaveBatch()` 均未对 `skinTestFlag` 做类型归一化处理,导致 0/"0"/"false"/undefined 等类型混用

修复:
- **
- 文件:** `openhis-ui-vue3/src/views/inpatientDoctor/home/components/order/index.vue`
- | # | 位置 | 变更内容 |
- |---|---|---|
- | 1 | 模板-皮试列 | `<span>` 只读文本 → 新增 `<el-checkbox v-else>` 可编辑复选框(`true-label=1`, `false-label=0`),编辑状态下医生可手动切换皮试标志 |
- | 2 | `getListInfo()` | 加载已保存医嘱时,从 `contentJson` 恢复 `skinTestFlag` 并归一化为数字类型 |
- | 3 | `selectAdviceBase()` | 选中药品后检测 `row.skinTestFlag == 1` → 弹出 `ElMessageBox.confirm` 对话框:"【皮试确认】当前药品是皮试药品,是否皮试?";[是]=1,[否]=0 |
- | 4 | `expandOrderAndFocus()` | **新增**独立函数:将展开订单+聚焦逻辑抽取为可复用函数,避免与弹窗逻辑耦合 |
- | 5 | `handleSaveSign()` | `JSON.stringify(row)` 前归一化 `skinTestFlag` 为数字类型 |
- | 6 | `handleSaveBatch()` | 批量保存时归一化 `skinTestFlag` 为数字类型 |
- | 7 | `setValue()` | 构建 `updatedRow` 时归一化 `skinTestFlag` 为数字类型 |
- 全链路覆盖(6 环验证):**
-  **录入**:选择皮试药品 → 弹窗确认(是/否)
-  **保存**:`handleSaveSign` + `handleSaveBatch` 均归一化 `skinTestFlag` 后写入 `contentJson`
-  **查询**:`getListInfo` 从 `contentJson` 恢复 `skinTestFlag`
-  **修改**:`setValue` 归一化,模板复选框可编辑
-  **删除/撤回**:原有删除逻辑 unaffected(`contentJson` 包含 `skinTestFlag`)
-  **关联模块**:不涉及其他模块(皮试字段仅在该页面交互)
This commit is contained in:
2026-05-29 08:58:03 +08:00
parent 154decbaa1
commit 775785df21

View File

@@ -296,6 +296,14 @@
<span v-if="!scope.row.isEdit">
{{ scope.row.skinTestFlag_enumText || '-' }}
</span>
<el-checkbox
v-else
v-model="scope.row.skinTestFlag"
:true-label="1"
:false-label="0"
>
</el-checkbox>
</template>
</el-table-column>
<el-table-column label="诊断" align="center" prop="diagnosisName" width="150">
@@ -632,6 +640,13 @@ function getListInfo(addNewRow) {
// 确保 therapyEnum 被正确设置,优先使用 contentJson 中的值
therapyEnum: String(parsedContent?.therapyEnum ?? item.therapyEnum ?? '1'),
// 🔧 修复:确保 orgId 为 String 类型,与 organization 树的 id 类型一致
// 确保 skinTestFlag 是数字类型1 或 0从 contentJson 恢复
skinTestFlag: parsedContent?.skinTestFlag !== undefined && parsedContent?.skinTestFlag !== null
? (typeof parsedContent.skinTestFlag === 'number' ? parsedContent.skinTestFlag : (parsedContent.skinTestFlag ? 1 : 0))
: 0,
skinTestFlag_enumText: parsedContent?.skinTestFlag !== undefined && parsedContent?.skinTestFlag !== null
? (parsedContent.skinTestFlag == 1 ? '是' : '否')
: '否',
// 关键:优先使用 item.positionId后端 @JsonSerialize 保证精度),
// 而非 parsedContent.orgId来自 JSON.parse大 Long 可能精度丢失)
// 使用 resolveOrgId 从组织树中匹配正确的 String id
@@ -963,15 +978,55 @@ function selectAdviceBase(key, row) {
setValue(row);
// 确保 uniqueKey 不被覆盖
prescriptionList.value[rowIndex.value].uniqueKey = currentUniqueKey;
// 先清空展开状态,然后在 nextTick 中设置,确保数据更新后再展开
// 检查是否是皮试药品,如果是则弹出确认提示
// 只对药品类型adviceType=1 药品, adviceType=2 耗材)进行皮试提示
const isSkinTestDrug = row.skinTestFlag !== undefined && row.skinTestFlag !== null
? (typeof row.skinTestFlag === 'number' ? row.skinTestFlag == 1 : (row.skinTestFlag ? true : false))
: false;
if ((row.adviceType == 1 || row.adviceType == 2) && isSkinTestDrug) {
// 弹出皮试确认弹窗
ElMessageBox.confirm(
`【皮试确认】当前药品是皮试药品,是否皮试?`,
'提示',
{
confirmButtonText: '是(Y)',
cancelButtonText: '否(N)',
type: 'warning',
closeOnClickModal: false,
closeOnPressEscape: false,
distinguishCancelAndClose: true,
}
)
.then(() => {
// 用户点击"是",设置皮试标志为"是"
prescriptionList.value[rowIndex.value].skinTestFlag = 1;
prescriptionList.value[rowIndex.value].skinTestFlag_enumText = '是';
expandOrderAndFocus(currentUniqueKey, row);
})
.catch((action) => {
// 用户点击"否",设置皮试标志为"否"
prescriptionList.value[rowIndex.value].skinTestFlag = 0;
prescriptionList.value[rowIndex.value].skinTestFlag_enumText = '否';
expandOrderAndFocus(currentUniqueKey, row);
});
} else {
// 不是皮试药品,直接展开订单
expandOrderAndFocus(currentUniqueKey, row);
}
}
/**
* 展开订单并聚焦输入框
*/
function expandOrderAndFocus(key, row) {
expandOrder.value = [];
nextTick(() => {
// 使用双重 nextTick 确保 filterPrescriptionList 已更新
nextTick(() => {
expandOrder.value = [currentUniqueKey];
// 如果 expand-row-keys 不生效,使用 toggleRowExpansion 强制展开
expandOrder.value = [key];
const tableData = filterPrescriptionList.value;
const targetRow = tableData.find((item) => item.uniqueKey === currentUniqueKey);
const targetRow = tableData.find((item) => item.uniqueKey === key);
if (targetRow && prescriptionRef.value) {
prescriptionRef.value.toggleRowExpansion(targetRow, true);
}
@@ -988,6 +1043,7 @@ function selectAdviceBase(key, row) {
});
}
function getOrgList() {
getOrgTree().then((res) => {
organization.value = res?.data?.records ?? res?.data ?? [];
@@ -1389,6 +1445,11 @@ function handleSaveSign(row, index) {
if (row.injectFlag == 1) {
row.sortNumber = row.sortNumber ? row.sortNumber : prescriptionList.value.length;
}
// 确保 skinTestFlag 是数字类型1 或 0
row.skinTestFlag = row.skinTestFlag !== undefined && row.skinTestFlag !== null
? (typeof row.skinTestFlag === 'number' ? row.skinTestFlag : (row.skinTestFlag ? 1 : 0))
: 0;
row.skinTestFlag_enumText = row.skinTestFlag == 1 ? '是' : '否';
row.contentJson = JSON.stringify(row);
if (row.requestId) {
row.dbOpType = '2';
@@ -1433,6 +1494,11 @@ function handleSaveBatch() {
...item,
therapyEnum: therapyEnum,
dbOpType: item.requestId ? '2' : '1',
// 确保 skinTestFlag 是数字类型1 或 0
skinTestFlag: item.skinTestFlag !== undefined && item.skinTestFlag !== null
? (typeof item.skinTestFlag === "number" ? item.skinTestFlag : (item.skinTestFlag ? 1 : 0))
: 0,
skinTestFlag_enumText: item.skinTestFlag == 1 ? '是' : '否',
};
});
if (saveList.length == 0) {
@@ -1538,6 +1604,13 @@ function setValue(row) {
minUnitCode: String(row.minUnitCode),
unitCode: row.partAttributeEnum == 1 ? String(row.minUnitCode) : String(row.unitCode),
categoryEnum: row.categoryCode,
// 确保 skinTestFlag 是数字类型1 或 0如果未定义则默认为 0
skinTestFlag: row.skinTestFlag !== undefined && row.skinTestFlag !== null
? (typeof row.skinTestFlag === 'number' ? row.skinTestFlag : (row.skinTestFlag ? 1 : 0))
: 0,
skinTestFlag_enumText: (row.skinTestFlag !== undefined && row.skinTestFlag !== null
? (typeof row.skinTestFlag === 'number' ? (row.skinTestFlag == 1 ? '是' : '否') : (row.skinTestFlag ? '是' : '否'))
: '否'),
definitionId: row.chargeItemDefinitionId,
executeNum: 1,
...(row.adviceType != 3