Files
his/openhis-ui-vue3/src/views/basicmanage/medicalOrderSet/components/MedicalOrderSetDialog.vue
chenqi dc67c00d20 refactor(ui): 更新组件属性以符合新版本规范
- 将所有组件中的 append-to-body 属性替换为 teleported
- 为 el-radio 和 el-checkbox 组件添加正确的 value 属性
- 移除已弃用的 highlight-current-row 属性
- 为 vxe-table 添加 row-config 配置替代旧的高亮设置
- 更新 el-checkbox 的 true-value 属性值
- 修改 el-button 类型从 text 到 link 以匹配设计系统
2026-06-04 16:04:17 +08:00

1041 lines
31 KiB
Vue
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
v-model="dialogVisible"
:title="dialogTitle"
width="1300px"
@close="handleDialogClose"
>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="80px"
>
<div class="dialog-top-row">
<el-form-item
label="名称"
prop="name"
>
<el-input
v-model="formData.name"
placeholder="请输入名称"
style="width: 220px"
/>
</el-form-item>
<el-form-item
v-if="showRangeSelector && !isEdit"
label="使用范围"
>
<el-select
v-model="rangeSelectValue"
placeholder="个人/科室/全院"
style="width: 220px"
@change="handleRangeChange"
>
<el-option
label="个人"
value="personal"
/>
<el-option
label="科室"
value="department"
/>
<el-option
label="全院"
value="hospital"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="currentTab === 'personal' && !isDoctorStation && !showRangeSelector"
label="参与者"
prop="practitionerId"
>
<el-select
v-model="formData.practitionerId"
placeholder="请选择参与者"
clearable
style="width: 220px"
>
<el-option
v-for="item in participantListOptions"
:key="item.practitionerId"
:label="item.practitionerName"
:value="item.practitionerId"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="currentTab === 'department'"
label="科室"
prop="organizationId"
>
<el-tree-select
v-model="formData.organizationId"
clearable
:data="organization"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="id"
check-strictly
default-expand-all
placeholder="请选择科室"
style="width: 220px"
:render-after-expand="false"
@change="handleOrgChange"
/>
</el-form-item>
</div>
</el-form>
<div style="margin-bottom: 10px">
<el-button
type="primary"
@click="handleAddRow"
>
新增
</el-button>
<el-button @click="handleCombineGroup">
组合
</el-button>
<el-button @click="handleSplitGroup">
拆组
</el-button>
</div>
<vxe-table
ref="prescriptionRef"
max-height="650"
:data="prescriptionList"
:row-config="{ keyField: 'uniqueKey', expandRowKeys: expandOrder }"
border
@cell-click="clickRow"
@checkbox-change="handleSelectionChange"
>
<vxe-column
type="checkbox"
width="55"
:selectable="isRowSelectable"
/>
<vxe-column
title="组"
align="center"
width="60"
>
<template #default="scope">
<span v-if="scope.row.groupId">{{ getGroupIcon(scope.row) }}</span>
</template>
</vxe-column>
<vxe-column
title="类型"
align="center"
width="120"
>
<template #default="scope">
<template v-if="!scope.row.groupPackageId">
<el-radio-group
v-model="scope.row.therapyEnum"
size="small"
>
<el-radio-button value="1">
长期
</el-radio-button>
<el-radio-button value="2">
临时
</el-radio-button>
</el-radio-group>
</template>
<span v-else>
{{
scope.row.therapyEnum == '1' ? '长期' : scope.row.therapyEnum == '2' ? '临时' : '-'
}}
</span>
</template>
</vxe-column>
<vxe-column
title="医嘱"
align="center"
field="productName"
width="300"
>
<template #default="scope">
<template v-if="getRowDisabled(scope.row)">
<el-popover
:popper-style="{ padding: '0' }"
placement="bottom-start"
:visible="scope.row.showPopover"
:width="1200"
>
<adviceBaseList
ref="adviceTableRef"
:popover-visible="scope.row.showPopover"
:advice-query-params="adviceQueryParams"
@select-advice-base="(row) => selectAdviceBase(scope.row.uniqueKey, row)"
/>
<template #reference>
<el-input
:ref="'adviceRef' + scope.rowIndex"
v-model="scope.row.adviceName"
style="width: 100%"
placeholder="请选择项目"
@input="(value) => handleInput(value, scope.row, scope.rowIndex)"
@click="handleFocus(scope.row, scope.rowIndex)"
@keyup.enter.stop="handleFocus(scope.row, scope.rowIndex)"
@keydown="
(e) => {
if (!scope.row.showPopover) return;
if (['ArrowUp', 'ArrowDown', 'Enter'].includes(e.key)) {
e.preventDefault();
adviceTableRef.handleKeyDown(e);
}
}
"
@blur="handleBlur(scope.row)"
/>
</template>
</el-popover>
</template>
<span v-else>{{ scope.row.adviceName }}</span>
</template>
</vxe-column>
<vxe-column
title="单次剂量"
align="center"
width="250"
field="sortNumber"
>
<template #default="scope">
<template v-if="!scope.row.groupPackageId">
<template v-if="scope.row.adviceType == 1 || !scope.row.adviceDefinitionId">
<!-- 新增/未保存行:统一按"数量 + 单位 = 剂量 + 单位"展示 -->
<el-input
v-model="scope.row.doseQuantity"
style="width: 70px; margin-right: 10px"
@input="
(value) => {
scope.row.dose = value * scope.row.unitConversionRatio;
}
"
/>
<span>
{{
scope.row.minUnitCode_dictText ||
scope.row.unitCodeName ||
scope.row.unitCode_dictText ||
''
}}
</span>
<span>{{ ' = ' }}</span>
<el-input
v-model="scope.row.dose"
style="width: 70px; margin-right: 10px"
@input="
(value) => {
scope.row.doseQuantity = value / scope.row.unitConversionRatio;
}
"
/>
<span>
{{
scope.row.doseUnitCode_dictText ||
scope.row.unitCodeName ||
scope.row.unitCode_dictText ||
''
}}
</span>
</template>
<span v-else>-</span>
</template>
<template v-else>
<span v-if="scope.row.adviceType == 1">{{ scope.row.dose }}</span>
<span v-else>-</span>
</template>
</template>
</vxe-column>
<vxe-column
title="给药途径"
align="center"
width="150"
field="sortNumber"
>
<template #default="scope">
<template v-if="!scope.row.groupPackageId">
<template v-if="scope.row.adviceType == 1 || !scope.row.adviceDefinitionId">
<el-select
v-model="scope.row.methodCode"
placeholder="给药途径"
clearable
filterable
>
<el-option
v-for="dict in method_code"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</template>
<span v-else>-</span>
</template>
<template v-else>
<span v-if="scope.row.adviceType == 1">{{ scope.row.methodCode_dictText || scope.row.methodCode }}</span>
<span v-else>-</span>
</template>
</template>
</vxe-column>
<vxe-column
title="用药频次"
align="center"
width="150"
field="sortNumber"
>
<template #default="scope">
<template v-if="!scope.row.groupPackageId">
<template v-if="scope.row.adviceType == 1 || !scope.row.adviceDefinitionId">
<el-select
v-model="scope.row.rateCode"
placeholder="频次"
style="width: 120px"
filterable
>
<el-option
v-for="dict in getRateOptions(scope.row)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</template>
<span v-else>-</span>
</template>
<template v-else>
<span v-if="scope.row.adviceType == 1">{{ scope.row.rateCode_dictText }}</span>
<span v-else>-</span>
</template>
</template>
</vxe-column>
<vxe-column
title="用药天数"
align="center"
width="100"
field="sortNumber"
>
<template #default="scope">
<template v-if="!scope.row.groupPackageId">
<template v-if="scope.row.adviceType == 1 || !scope.row.adviceDefinitionId">
<el-input
v-model="scope.row.dispensePerDuration"
@change="handleQuantityChange(scope.row)"
/>
</template>
<span v-else>-</span>
</template>
<template v-else>
<span v-if="scope.row.adviceType == 1">{{ scope.row.dispensePerDuration }}</span>
<span v-else>-</span>
</template>
</template>
</vxe-column>
<vxe-column
title="总量/执行次数"
align="center"
width="150"
field="sortNumber"
>
<template #default="scope">
<template v-if="!scope.row.groupPackageId">
<el-input
v-model="scope.row.sortNumber"
type="number"
min="1"
@change="handleQuantityChange(scope.row)"
/>
</template>
<span v-else>{{ scope.row.sortNumber }}</span>
</template>
</vxe-column>
<vxe-column
title="单位"
align="center"
width="120"
field="unitCode"
>
<template #default="scope">
<template v-if="!scope.row.groupPackageId">
<el-select
v-model="scope.row.selectUnitCode"
placeholder="请选择单位"
@change="handleUnitChange(scope.row)"
>
<el-option
v-if="scope.row.minUnitCode"
:key="scope.row.minUnitCode"
:label="scope.row.minUnitCode_dictText || scope.row.minUnitCode"
:value="scope.row.minUnitCode"
/>
<el-option
v-if="scope.row.unitCode"
:key="scope.row.unitCode"
:label="scope.row.unitCode_dictText || scope.row.unitCode"
:value="scope.row.unitCode"
/>
</el-select>
</template>
<span>{{ scope.row.unitCodeName }}</span>
</template>
</vxe-column>
<vxe-column
title="操作"
align="center"
width="80"
>
<template #default="scope">
<el-button
type="danger"
icon="Delete"
circle
size="small"
@click="handleDeleteRow(scope.rowIndex, scope.row)"
/>
</template>
</vxe-column>
</vxe-table>
<template #footer>
<el-button @click="dialogVisible = false">
取 消
</el-button>
<el-button
type="primary"
:loading="submitLoading"
@click="submitForm"
>
</el-button>
</template>
</el-dialog>
</template>
<script setup>
import { ref, reactive, computed, onMounted, getCurrentInstance } from 'vue';
import adviceBaseList from './adviceBaseList';
import {
queryParticipantList,
queryGroupDetail,
getOrgTree,
} from './api.js';
import { saveOrderGroup } from '@/views/doctorstation/components/api.js';
import useUserStore from '@/store/modules/user';
import { ElMessage } from 'element-plus';
const props = defineProps({
// 是否在“医生站/住院医生站”场景复用个人不选人practitionerId 置空),科室可选科室
isDoctorStation: {
type: Boolean,
default: false,
},
method_code: {
type: Array,
default: () => [],
},
rate_code: {
type: Array,
default: () => [],
},
// 顶部是否显示“个人/科室/全院”切换(用于住院医生站顶部【组套】按钮场景)
showRangeSelector: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['saved']);
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
const dialogVisible = ref(false);
const dialogTitle = ref('');
const currentTab = ref('personal'); // personal | department | hospital
const isEdit = ref(false);
const submitLoading = ref(false);
const rangeSelectValue = ref('personal');
const participantListOptions = ref([]);
const organization = ref([]);
const adviceQueryParams = reactive({});
const formData = reactive({
groupPackageId: undefined,
name: '',
practitionerId: undefined,
organizationId: undefined,
});
const prescriptionList = ref([]);
const expandOrder = ref([]);
const nextId = ref(1);
const rowIndex = ref(0);
const selectedRows = ref([]);
const groupIndex = ref(1);
const formRef = ref();
const prescriptionRef = ref();
const adviceTableRef = ref();
const formRules = computed(() => {
const rules = {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
};
// 独立页面:个人必须选参与者;科室必须选科室
if (!props.isDoctorStation && currentTab.value === 'personal') {
rules.practitionerId = [{ required: true, message: '请选择参与者', trigger: 'change' }];
}
if (currentTab.value === 'department') {
rules.organizationId = [{ required: true, message: '请选择科室', trigger: 'change' }];
}
return rules;
});
onMounted(() => {
queryParticipantList().then((res) => {
participantListOptions.value = res.data || [];
});
getOrgTree().then((res) => {
organization.value = res.data?.records || [];
});
});
function openAdd(tab) {
currentTab.value = tab;
isEdit.value = false;
dialogTitle.value = '新增医嘱';
dialogVisible.value = true;
if (props.showRangeSelector) rangeSelectValue.value = tab;
prescriptionList.value = [];
expandOrder.value = [];
nextId.value = 1;
rowIndex.value = 0;
selectedRows.value = [];
groupIndex.value = 1;
formData.groupPackageId = undefined;
formData.name = '';
formData.practitionerId = undefined;
formData.organizationId = undefined;
Object.keys(adviceQueryParams).forEach((key) => {
delete adviceQueryParams[key];
});
prescriptionRef.value?.clearSelection?.();
if (tab === 'personal') {
// 医生站场景:个人组套需要关联当前医生才能查询到
formData.practitionerId = userStore.practitionerId;
} else if (tab === 'department') {
formData.organizationId = userStore.orgId;
}
addEmptyRow();
}
function handleRangeChange(tab) {
openAdd(tab);
}
/**
* 从外部选中的医嘱直接生成组套明细
* @param tab 使用范围personal / department / hospital
* @param rows 选中的处方行列表
*/
function openFromSelection(tab, rows = []) {
currentTab.value = tab;
isEdit.value = false;
dialogTitle.value = '另存组套';
dialogVisible.value = true;
if (props.showRangeSelector) rangeSelectValue.value = tab;
// 重置表单
formData.groupPackageId = undefined;
formData.name = '';
formData.practitionerId = undefined;
formData.organizationId = undefined;
if (tab === 'personal') {
// 医生站场景:个人组套需要关联当前医生才能查询到
formData.practitionerId = userStore.practitionerId;
} else if (tab === 'department') {
formData.organizationId = userStore.orgId;
}
const validRows = (rows || []).filter((i) => i.adviceDefinitionId);
if (validRows.length === 0) {
proxy.$modal.msgWarning('所选医嘱中没有有效的医嘱项,请先选择医嘱后再另存组套');
dialogVisible.value = false;
return;
}
prescriptionList.value = validRows.map((row, index) => {
let therapyEnum = row.therapyEnum;
if (!therapyEnum && row.contentJson) {
try {
const content = JSON.parse(row.contentJson);
therapyEnum = content.therapyEnum;
} catch (e) {}
}
therapyEnum = therapyEnum != null ? String(therapyEnum) : '1';
return {
uniqueKey: index + 1,
showPopover: false,
check: false,
isEdit: false,
statusEnum: 1,
adviceDefinitionId: row.adviceDefinitionId,
adviceTableName: row.adviceTableName || 'advice_definition',
sortNumber: row.quantity ?? row.sortNumber ?? 1,
selectUnitCode: row.selectUnitCode || row.unitCode,
adviceName: row.adviceName || row.productName,
unitCodeName: row.unitCodeName || row.unitCode_dictText || '',
methodCode: row.methodCode,
rateCode: row.rateCode,
dispensePerDuration: row.dispensePerDuration,
dose: row.dose,
doseQuantity: row.doseQuantity,
minUnitCode: row.minUnitCode,
minUnitCode_dictText: row.minUnitCode_dictText,
unitCode: row.unitCode,
unitCode_dictText: row.unitCode_dictText,
groupId: row.groupId,
groupOrder: row.groupOrder,
therapyEnum: therapyEnum,
adviceType: row.adviceType,
};
});
expandOrder.value = [];
nextId.value = prescriptionList.value.length + 1;
}
function openEdit(tab, row) {
currentTab.value = tab;
isEdit.value = true;
dialogTitle.value = '编辑医嘱';
dialogVisible.value = true;
formData.groupPackageId = row.groupPackageId;
formData.name = row.name;
formData.practitionerId = row.practitionerId;
formData.organizationId = row.organizationId;
queryGroupDetail({ groupPackageId: row.groupPackageId }).then((res) => {
const detailList = res.data || [];
prescriptionList.value = detailList.map((item, index) => {
const therapyEnum = item.therapyEnum != null ? String(item.therapyEnum) : '1'; // 统一转成字符串
return {
uniqueKey: index + 1,
showPopover: false,
check: false,
isEdit: false,
statusEnum: 1,
groupPackageId: item.groupPackageId,
adviceDefinitionId: item.orderDefinitionId,
adviceTableName: item.orderDefinitionTable,
sortNumber: item.quantity,
selectUnitCode: item.unitCode,
adviceName: item.orderDefinitionName,
unitCodeName: item.unitCodeName,
groupId: item.groupId,
groupOrder: item.groupOrder,
therapyEnum, // 长期/临时类型1-长期2-临时
// 回显单次剂量/给药途径/用药频次/天数等字段
dispensePerDuration: item.dispensePerDuration,
dose: item.dose,
doseQuantity: item.doseQuantity,
methodCode: item.methodCode,
methodCode_dictText: item.methodCode_dictText,
rateCode: item.rateCode,
rateCode_dictText: item.rateCode_dictText,
// 医嘱类型(药品=1没有则按表名推断药品表 -> 药品)
adviceType:
item.adviceType !== undefined
? item.adviceType
: item.orderDefinitionTable === 'med_medication_definition'
? 1
: undefined,
};
});
nextId.value = prescriptionList.value.length + 1;
addEmptyRow();
});
}
function addEmptyRow() {
prescriptionList.value.unshift({
uniqueKey: nextId.value++,
showPopover: false,
check: false,
isEdit: true,
statusEnum: 1,
therapyEnum: '1', // 默认长期
});
}
function handleAddRow() {
addEmptyRow();
}
function handleSelectionChange(selection) {
selectedRows.value = selection || [];
}
function handleCombineGroup() {
const rows = selectedRows.value || [];
if (rows.length <= 1) {
proxy.$modal.msgWarning('至少选择两项');
return;
}
// 必须都已选择医嘱
if (rows.some((r) => !r.adviceDefinitionId)) {
proxy.$modal.msgWarning('请先完成医嘱选择');
return;
}
// 相同分组用法需要相同
const methodSet = new Set();
rows.forEach((r) => {
if (r.methodCode != null) methodSet.add(r.methodCode);
});
if (methodSet.size > 1) {
proxy.$modal.msgWarning('同一分组药品用法必须相同');
return;
}
// 相同分组频次需要相同
const rateSet = new Set();
rows.forEach((r) => {
if (r.rateCode != null) rateSet.add(r.rateCode);
});
if (rateSet.size > 1) {
proxy.$modal.msgWarning('同一分组药品频次必须相同');
return;
}
const timestamp = Date.now().toString();
const gid = timestamp + groupIndex.value;
const newList = [...prescriptionList.value];
rows.forEach((item, selectIndex) => {
const idx = newList.findIndex((r) => r.uniqueKey === item.uniqueKey);
if (idx !== -1) {
newList[idx].groupId = gid;
newList[idx].groupOrder = selectIndex + 1;
}
});
groupIndex.value += 1;
prescriptionList.value = newList;
prescriptionRef.value?.clearSelection?.();
proxy.$modal.msgSuccess('组套成功');
}
function isRowSelectable(row) {
return !!row.adviceDefinitionId;
}
function getGroupIcon(row) {
if (!row.groupId) return '';
const sameGroup = prescriptionList.value
.filter((item) => item.groupId === row.groupId)
.sort((a, b) => {
const aOrder = a.groupOrder ?? 0;
const bOrder = b.groupOrder ?? 0;
return aOrder - bOrder;
});
if (sameGroup.length === 0) return '';
const index = sameGroup.findIndex((item) => item.uniqueKey === row.uniqueKey);
if (index === 0) {
return '┏';
}
if (index === sameGroup.length - 1) {
return '┗';
}
return '┃';
}
function getRateOptions(row) {
const all = props.rate_code || [];
if (row?.therapyEnum == '2') {
return all.filter(
(dict) => dict.value === 'ST' || (dict.label && dict.label.indexOf('立即') !== -1)
);
}
return all;
}
function handleSplitGroup() {
const rows = selectedRows.value || [];
if (rows.length < 1) {
proxy.$modal.msgWarning('至少选择一项');
return;
}
if (rows.some((r) => !r.groupId)) {
proxy.$modal.msgWarning('包含非组合数据无法拆组');
return;
}
const newList = [...prescriptionList.value];
rows.forEach((item) => {
const idx = newList.findIndex((r) => r.uniqueKey === item.uniqueKey);
if (idx !== -1) {
newList[idx].groupId = undefined;
newList[idx].groupOrder = undefined;
}
});
prescriptionList.value = newList;
prescriptionRef.value?.clearSelection?.();
proxy.$modal.msgSuccess('拆组成功');
}
function submitForm() {
formRef.value.validate((valid) => {
if (!valid) return;
// 验证至少选择了一条医嘱
const detailList = prescriptionList.value.filter((item) => item.adviceDefinitionId);
if (detailList.length === 0) {
proxy?.$modal?.msgWarning?.('请至少选择一条医嘱');
return;
}
// 验证西药类医嘱的必填字段
const westernMedicineRows = detailList.filter((item) => item.adviceType == 1);
for (const row of westernMedicineRows) {
if (!row.dose && row.dose !== 0) {
proxy?.$modal?.msgWarning?.('单次剂量为必填项');
return;
}
if (!row.methodCode) {
proxy?.$modal?.msgWarning?.('给药途径为必填项');
return;
}
if (!row.rateCode) {
proxy?.$modal?.msgWarning?.('用药频次为必填项');
return;
}
if (!row.dispensePerDuration && row.dispensePerDuration !== 0) {
proxy?.$modal?.msgWarning?.('用药天数为必填项');
return;
}
if (!row.sortNumber && row.sortNumber !== 0) {
proxy?.$modal?.msgWarning?.('总量/执行次数为必填项');
return;
}
if (!row.selectUnitCode) {
proxy?.$modal?.msgWarning?.('单位为必填项');
return;
}
}
submitLoading.value = true;
setTimeout(() => {
console.log('[submitForm] 当前tab:', currentTab.value);
const params = { ...formData };
console.log('[submitForm] formData:', formData);
// 添加 rangeCode 字段,用于后端判断组套类型
if (currentTab.value === 'personal') {
params.rangeCode = 1;
} else if (currentTab.value === 'department') {
params.rangeCode = 2;
} else {
params.rangeCode = 3;
}
console.log('[submitForm] 设置后的rangeCode:', params.rangeCode);
// 医生站场景:个人组套需要设置 practitionerId 为当前医生,否则查询时查不到
console.log('[submitForm] isDoctorStation:', props.isDoctorStation, 'currentTab:', currentTab.value);
console.log('[submitForm] userStore.practitionerId:', userStore.practitionerId);
if (props.isDoctorStation && currentTab.value === 'personal') {
params.practitionerId = userStore.practitionerId;
console.log('[submitForm] 已设置 practitionerId:', params.practitionerId);
} else {
console.log('[submitForm] 未设置 practitionerId, 当前值:', params.practitionerId);
}
params.detailList = detailList.map((item) => ({
orderDefinitionId: item.adviceDefinitionId,
orderDefinitionTable: item.adviceTableName,
quantity: item.sortNumber,
unitCode: item.selectUnitCode,
methodCode: item.methodCode,
rateCode: item.rateCode,
dispensePerDuration: item.dispensePerDuration,
dose: item.dose,
doseQuantity: item.doseQuantity,
groupId: item.groupId,
groupOrder: item.groupOrder,
therapyEnum: item.therapyEnum || '1',
}));
console.log('[submitForm] 准备保存组套, params:', params);
// 使用 saveOrderGroup它会根据 rangeCode 自动选择正确的API
saveOrderGroup(params)
.then((res) => {
console.log('[submitForm] 保存API返回:', res);
if (res.code === 200) {
ElMessage.success(res.message || '保存成功');
console.log('[submitForm] 准备触发 saved 事件');
emit('saved');
console.log('[submitForm] saved 事件已触发');
dialogVisible.value = false;
prescriptionList.value = [];
} else {
proxy?.$modal?.msgError?.(res.message || '保存失败');
}
})
.catch((err) => {
console.error('保存失败:', err);
proxy?.$modal?.msgError?.(err?.message || '保存失败,请检查网络或联系管理员');
})
.finally(() => {
submitLoading.value = false;
});
}, 200);
});
}
function selectAdviceBase(key, row) {
const currentRow = prescriptionList.value[rowIndex.value];
const preservedTherapyEnum = currentRow?.therapyEnum || row.therapyEnum || '1';
prescriptionList.value[rowIndex.value] = {
...prescriptionList.value[rowIndex.value],
...JSON.parse(JSON.stringify(row)),
};
prescriptionList.value[rowIndex.value].dose = undefined;
prescriptionList.value[rowIndex.value].doseQuantity = undefined;
prescriptionList.value[rowIndex.value].doseUnitCode = row.doseUnitCode;
prescriptionList.value[rowIndex.value].minUnitCode = row.minUnitCode;
prescriptionList.value[rowIndex.value].unitCode =
row.partAttributeEnum == 1 ? row.minUnitCode : row.unitCode;
prescriptionList.value[rowIndex.value].categoryEnum = row.categoryCode;
prescriptionList.value[rowIndex.value].isEdit = false;
prescriptionList.value[rowIndex.value].definitionId = JSON.parse(
JSON.stringify(row)
).chargeItemDefinitionId;
prescriptionList.value[rowIndex.value].therapyEnum = preservedTherapyEnum;
addEmptyRow();
expandOrder.value = [key];
}
function handleFocus(row, index) {
rowIndex.value = index;
row.showPopover = true;
adviceQueryParams.searchKey = row.adviceName || '';
// 设置 organizationId否则 adviceBaseList 会跳过 API 调用
adviceQueryParams.organizationId = userStore.orgId;
}
function handleInput(value, row, index) {
adviceQueryParams.searchKey = value || '';
handleFocus(row, index);
}
function handleBlur(row) {
row.showPopover = false;
}
function clickRow() {}
function getRowDisabled(row) {
return row.isEdit;
}
function handleQuantityChange(row) {
if (row.sortNumber && row.sortNumber > 0) row.sortNumber = parseInt(row.sortNumber);
else row.sortNumber = 1;
prescriptionList.value = [...prescriptionList.value];
}
function handleUnitChange(row) {
prescriptionList.value = [...prescriptionList.value];
}
function handleDeleteRow(index) {
if (prescriptionList.value.length <= 1) {
proxy.$modal.msgWarning('至少保留一行');
return;
}
proxy.$modal
.confirm('确定要删除该行吗?')
.then(() => {
prescriptionList.value.splice(index, 1);
proxy.$modal.msgSuccess('删除成功');
})
.catch(() => {});
}
function isLeafNode(node) {
return !node.children || node.children.length === 0;
}
function handleDialogClose() {
formRef.value?.resetFields?.();
prescriptionList.value = [];
}
function handleOrgChange(value) {
if (!value) return;
const findNode = (nodes) => {
for (let node of nodes) {
if (node.id === value) return node;
if (node.children && node.children.length > 0) {
const found = findNode(node.children);
if (found) return found;
}
}
return null;
};
const selectedNode = findNode(organization.value);
if (selectedNode && !isLeafNode(selectedNode)) {
proxy.$modal.msgWarning('只能选择末级科室');
formData.organizationId = null;
}
}
defineExpose({
openAdd,
openEdit,
openFromSelection,
});
</script>
<style scoped>
.dialog-top-row {
display: flex;
align-items: center;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 10px;
}
.dialog-top-row :deep(.el-form-item) {
margin-bottom: 0;
}
</style>