feat(basicmanage): 新增医嘱组套对话框组件和相关API

- 实现 MedicalOrderSetDialog.vue 组件,支持医嘱组套的新增、编辑功能
- 添加中药医嘱基础列表组件 tcmMedicineList.vue,支持键盘导航选择
- 创建医嘱组套相关API接口文件,包含个人、科室、全院组套的增删改查功能
- 实现医嘱组套的组合拆组功能,支持批量操作
- 集成分页、搜索、缓存等优化功能提升用户体验
- 添加表单验证和数据校验机制确保数据完整性
This commit is contained in:
2026-03-17 09:35:07 +08:00
parent 16f6fbb8cf
commit 03939fb232
4 changed files with 2103 additions and 0 deletions

View File

@@ -0,0 +1,885 @@
<template>
<el-dialog :title="dialogTitle" v-model="dialogVisible" 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 label="使用范围" v-if="showRangeSelector && !isEdit">
<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
label="参与者"
prop="practitionerId"
v-if="currentTab === 'personal' && !isDoctorStation && !showRangeSelector"
>
<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 label="科室" prop="organizationId" v-if="currentTab === 'department'">
<el-tree-select
clearable
v-model="formData.organizationId"
: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>
<el-table
max-height="650"
ref="prescriptionRef"
:data="prescriptionList"
row-key="uniqueKey"
border
@cell-click="clickRow"
@selection-change="handleSelectionChange"
:expand-row-keys="expandOrder"
>
<el-table-column type="selection" width="55" :selectable="isRowSelectable" />
<el-table-column label="组" align="center" width="60">
<template #default="scope">
<span v-if="scope.row.groupId">{{ getGroupIcon(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column label="类型" 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 label="1">长期</el-radio-button>
<el-radio-button label="2">临时</el-radio-button>
</el-radio-group>
</template>
<span v-else>
{{
scope.row.therapyEnum == '1' ? '长期' : scope.row.therapyEnum == '2' ? '临时' : '-'
}}
</span>
</template>
</el-table-column>
<el-table-column label="医嘱" align="center" prop="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"
:popoverVisible="scope.row.showPopover"
:adviceQueryParams="adviceQueryParams"
@selectAdviceBase="(row) => selectAdviceBase(scope.row.uniqueKey, row)"
/>
<template #reference>
<el-input
:ref="'adviceRef' + scope.$index"
style="width: 100%"
v-model="scope.row.adviceName"
placeholder="请选择项目"
@input="(value) => handleInput(value, scope.row, scope.$index)"
@click="handleFocus(scope.row, scope.$index)"
@keyup.enter.stop="handleFocus(scope.row, scope.$index)"
@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>
</el-table-column>
<el-table-column label="单次剂量" align="center" width="250" prop="sortNumber">
<template #default="scope">
<template v-if="scope.row.adviceType == 1">
<!-- 新增/未保存行统一按数量 + 单位 = 剂量 + 单位展示 -->
<template v-if="!scope.row.groupPackageId">
<el-input
style="width: 70px; margin-right: 10px"
v-model="scope.row.doseQuantity"
@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
style="width: 70px; margin-right: 10px"
v-model="scope.row.dose"
@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>{{ scope.row.dose }}</span>
</template>
<span v-else>{{ '-' }}</span>
</template>
</el-table-column>
<el-table-column label="给药途径" align="center" width="150" prop="sortNumber">
<template #default="scope">
<template v-if="scope.row.adviceType == 1">
<template v-if="!scope.row.groupPackageId">
<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>{{ scope.row.methodCode }}</span>
</template>
<span v-else>{{ '-' }}</span>
</template>
</el-table-column>
<el-table-column label="用药频次" align="center" width="150" prop="sortNumber">
<template #default="scope">
<template v-if="scope.row.adviceType == 1">
<template v-if="!scope.row.groupPackageId">
<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>{{ scope.row.rateCode_dictText }}</span>
</template>
<span v-else>{{ '-' }}</span>
</template>
</el-table-column>
<el-table-column label="用药天数" align="center" width="100" prop="sortNumber">
<template #default="scope">
<template v-if="scope.row.adviceType == 1">
<template v-if="!scope.row.groupPackageId">
<el-input
v-model="scope.row.dispensePerDuration"
@change="handleQuantityChange(scope.row)"
/>
</template>
<span v-else>{{ scope.row.dispensePerDuration }}</span>
</template>
<span v-else>{{ '-' }}</span>
</template>
</el-table-column>
<el-table-column label="总量/执行次数" align="center" width="150" prop="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>
</el-table-column>
<el-table-column label="单位" align="center" width="120" prop="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>
</el-table-column>
<el-table-column label="操作" align="center" width="80">
<template #default="scope">
<el-button
type="danger"
icon="Delete"
circle
size="small"
@click="handleDeleteRow(scope.$index, scope.row)"
/>
</template>
</el-table-column>
</el-table>
<template #footer>
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitForm" :loading="submitLoading"> </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,
rateCode: item.rateCode,
// 医嘱类型(药品=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;
}
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>