Files
his/healthlink-his-ui/src/views/catalog/device/components/deviceDialog.vue
chenqi 52b94b9df4 refactor(icons): 优化SVG图标路径结构
- 移除多余的垂直线条路径定义
- 简化为三个水平条形路径,减少重复代码
- 保持图标的视觉表现一致性

fix(device): 修复设备对话框标题和选项初始化问题

- 移除冗余的标题赋值操作
- 删除未使用的分类、状态和供应商选项属性
- 保留必要的表单重置和树形结构加载逻辑
2026-06-17 15:00:54 +08:00

797 lines
24 KiB
Vue
Executable File

<template>
<div class="app-container">
<!-- 添加或修改用户配置对话框 -->
<el-dialog
v-model="visible"
:title="title"
width="955px"
teleported
>
<el-form
ref="deviceDialogRef"
:model="form"
:rules="rules"
label-width="110px"
label-position="left"
>
<div class="title">
<el-button
type="primary"
plain
size="small"
style="margin-left: 5px; margin-top: -10px; margin-bottom: 20px"
@click="handleImportYb()"
>
从医保目录导入
</el-button>
</div>
<el-row :gutter="24">
<el-col
v-if="form.id != undefined"
:span="8"
>
<el-form-item
label="编号"
prop="busNo"
>
<el-input
v-model="form.busNo"
clearable
placeholder="请输入编码"
disabled
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="器材名称"
prop="name"
>
<el-input
v-model="form.name"
clearable
placeholder="请输入器材名称"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="器材分类"
prop="categoryCode"
>
<el-tree-select
v-model="form.categoryCode"
:data="deviceCategories"
filterable
:props="{ value: 'value', label: 'info', children: 'children' }"
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
value-key="value"
check-strictly
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="器材种类"
prop="typeCode"
>
<el-select
v-model="form.typeCode"
clearable
filterable
>
<el-option
v-for="dict in device_type_code"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="提供部门"
prop="orgId"
>
<el-tree-select
v-model="form.orgId"
:data="deptOptions"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="id"
placeholder="请选择提供部门"
check-strictly
clearable
filterable
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="地点"
prop="locationId"
>
<el-tree-select
v-model="form.locationId"
:data="locationOptions"
:props="{ value: 'id', label: 'name', children: 'children' }"
value-key="id"
placeholder="请选择地点"
check-strictly
clearable
filterable
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="包装单位"
prop="unitCode"
>
<el-select
v-model="form.unitCode"
clearable
filterable
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
@change="handleUnitCodeChange"
>
<el-option
v-for="dict in unitCodeOptions"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="销售单位"
prop="salesUnitCode"
>
<el-select
v-model="form.salesUnitCode"
clearable
filterable
>
<el-option
v-for="dict in unit_code"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="最小单位"
prop="minUnitCode"
>
<el-select
v-model="form.minUnitCode"
clearable
filterable
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
>
<el-option
v-for="dict in unit_code"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="包装规格"
prop="size"
>
<el-input
v-model="form.size"
clearable
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="拆零比"
prop="partPercent"
>
<el-input-number
v-model="form.partPercent"
controls-position="right"
:min="1"
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="产品型号"
prop="modelNumber"
>
<el-input
v-model="form.modelNumber"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="批准文号"
prop="approvalNumber"
>
<el-input
v-model="form.approvalNumber"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="医保编码"
prop="ybNo"
>
<el-input
v-model="form.ybNo"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="医药机构目录编码"
prop="ybOrgNo"
label-width="125px"
>
<el-input
v-model="form.ybOrgNo"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="主要成分"
prop="substanceText"
>
<el-input
v-model="form.substanceText"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="警戒线最低值(常规单位)"
prop="itemMinQuantity"
label-width="180px"
>
<el-input-number
v-model="form.itemMinQuantity"
controls-position="right"
:min="0"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="警戒线最高值(常规单位)"
prop="itemMaxQuantity"
label-width="180px"
>
<el-input-number
v-model="form.itemMaxQuantity"
controls-position="right"
:min="0"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="生产厂家"
prop="manufacturerText"
>
<el-input
v-model="form.manufacturerText"
clearable
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="供应商"
prop="supplyId"
>
<el-select
v-model="form.supplyId"
filterable
clearable
style="width: 150px"
>
<el-option
v-for="supplier in supplierListOptions"
:key="supplier.value"
:label="supplier.label"
:value="supplier.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="过敏标记"
prop="allergenFlag"
>
<el-checkbox v-model="form.allergenFlag" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="医保标记"
prop="ybFlag"
>
<el-checkbox v-model="form.ybFlag" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="医保对码标记"
prop="ybMatchFlag"
>
<el-checkbox v-model="form.ybMatchFlag" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="高值器材标志"
prop="hvcmFlag"
>
<el-checkbox v-model="form.hvcmFlag" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="财务类型"
prop="itemTypeCode"
>
<el-select
v-model="form.itemTypeCode"
clearable
filterable
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
>
<el-option
v-for="category in fin_type_code"
:key="category.value"
:label="category.label"
:value="category.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="医保类别"
prop="ybType"
>
<el-select
v-model="form.ybType"
placeholder="医保类别"
clearable
filterable
style="width: 240px"
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
>
<el-option
v-for="dict in med_chrgitm_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="适用范围"
prop="jurisdiction"
>
<el-input
v-model="form.jurisdiction"
clearable
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="购入价"
prop="purchasePrice"
>
<el-input
v-model="form.purchasePrice"
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
@input="updatePrices"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="零售价"
prop="retailPrice"
>
<el-input
v-model="form.retailPrice"
clearable
:disabled="form.isEditInfoDisable === 1 || form.isEditInfoDisable === 2"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item
label="最高零售价"
prop="maximumRetailPrice"
>
<el-input
v-model="form.maximumRetailPrice"
clearable
:disabled="false"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item
label="医保等级"
prop="chrgitmLv"
>
<el-select
v-model="form.chrgitmLv"
placeholder="医保等级"
clearable
filterable
style="width: 240px"
:disabled="form.isEditInfoDisable === 1"
>
<el-option
v-for="dict in chrgitm_lv"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="16">
<el-form-item
label="说明"
prop="description"
>
<el-input
v-model="form.description"
:autosize="{ minRows: 4, maxRows: 10 }"
type="textarea"
clearable
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template
v-if="title != '查看'"
#footer
>
<div class="dialog-footer">
<el-button
type="primary"
@click="submitForm"
>
</el-button>
<el-button @click="cancel">
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="MedicineDialog">
import {addDevice, deptTreeSelect, editDevice, locationTreeSelect} from './device';
import {getDicts} from '@/api/system/dict/data';
const { proxy } = getCurrentInstance();
const { device_type_code, unit_code, fin_type_code, chrgitm_lv, med_chrgitm_type } = proxy.useDict(
'device_type_code',
'unit_code',
'fin_type_code',
'chrgitm_lv',
'med_chrgitm_type'
);
const visible = ref(false);
const emits = defineEmits(['submit']); // 声明自定义事件
const deptOptions = ref(undefined); // 部门树选项
const locationOptions = ref(undefined); // 地点树选项
const unitCodeOptions = ref([]); // 包装单位选项列表(用于搜索)
const unitCodeLoading = ref(false); // 包装单位搜索加载状态
const data = reactive({
form: {},
rules: {
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
categoryCode: [{ required: true, message: '器材分类不能为空', trigger: 'blur' }],
unitCode: [{ required: true, message: '包装单位不能为空', trigger: 'blur' }],
size: [{ required: true, message: '包装规格不能为空', trigger: 'blur' }],
partPercent: [{ required: true, message: '拆零比不能为空', trigger: 'blur' }],
minUnitCode: [{ required: true, message: '最小使用单位不能为空', trigger: 'blur' }],
itemMinQuantity: [{ required: true, message: '警戒线最低值不能为空', trigger: 'blur' }],
itemMaxQuantity: [{ required: true, message: '警戒线最高值不能为空', trigger: 'blur' }],
salesUnitCode: [{ required: true, message: '销售单位不能为空', trigger: 'blur' }],
manufacturerId: [{ required: true, message: '生产厂家不能为空', trigger: 'blur' }],
ruleId: [{ required: true, message: '执行科室不能为空', trigger: 'blur' }],
locationId: [{ required: true, message: '地点不能为空', trigger: 'blur' }],
purchasePrice: [{ required: true, message: '购入价不能为空', trigger: 'blur' }],
retailPrice: [{ required: true, message: '零售价不能为空', trigger: 'blur' }],
ybType: [{ required: true, message: '医保类型不能为空', trigger: 'blur' }],
chrgitmLv: [{ required: true, message: '医保等级不能为空', trigger: 'blur' }],
itemTypeCode: [{ required: true, message: '财务类型不能为空', trigger: 'blur' }],
},
});
const { form, rules } = toRefs(data);
const props = defineProps({
item: {
type: Object,
required: false,
},
title: {
type: String,
required: false,
},
deviceCategories: {
type: Object,
required: false,
},
statusFlagOptions: {
type: Object,
required: false,
},
currentCategoryEnum: {
type: String,
required: true,
},
supplierListOptions: {
type: Object,
required: false,
},
});
function handleImportYb() {
emits('ybDialog');
}
// 显示弹框
function show() {
reset();
form.value.categoryCode = props.currentCategoryEnum;
form.value.partPercent = 1;
form.value.itemTypeCode = '2005';
form.value.ybType = '08';
form.value.size = '-';
getDeptTree();
getLocationTree();
// 初始化包装单位列表
handleUnitCodeFocus();
visible.value = true;
}
//医保目录对照后,赋值
function setValue(row) {
form.value = {
name: formatValue(row.consumableName), //医疗服务项目名称
ybNo: formatValue(row.medicalCatalogCode), // 医保编码
modelNumber: formatValue(row.specification), // 规格
manufacturerText: formatValue(row.manufacturerName), // 厂家名称
partPercent: 1,
itemMinQuantity: formatValue(row.itemMinQuantity), // 警戒线最低值
itemMaxQuantity: formatValue(row.itemMaxQuantity), // 警戒线最高值
};
}
/** 查询部门下拉树结构 */
function getDeptTree() {
deptTreeSelect().then((response) => {
deptOptions.value = response.data.records;
});
}
/** 查询地点下拉树结构 */
function getLocationTree() {
locationTreeSelect({ formList: '11,16,17' }).then((response) => {
locationOptions.value = response.data.records;
});
}
// 显示弹框
function edit() {
reset();
form.value = props.item;
form.value.chrgitmLv = form.value.chrgitmLv ? form.value.chrgitmLv.toString() : undefined;
getDeptTree();
getLocationTree();
// 初始化包装单位列表
handleUnitCodeFocus();
visible.value = true;
}
/** 重置操作表单 */
function reset() {
form.value = {
id: undefined,
busNo: undefined, // 编码
name: undefined, // 名称
pyStr: undefined, // 拼音码
wbStr: undefined, // 五笔码
categoryCode: undefined, // 类别
typeCode: undefined, // 类型编码
unitCode: undefined, // 单位编码
size: undefined, // 规格
partPercent: undefined, // 占比
minUnitCode: undefined, // 最小单位编码
modelNumber: undefined, // 型号
hvcmFlag: undefined, // 高值器材标志
salesUnitCode: undefined, // 销售单位编码
approvalNumber: undefined, // 批准文号
ybFlag: undefined, // 医保标志
ybNo: undefined, // 医保编码
ybOrgNo: undefined, //医药机构目录编码
ybMatchFlag: undefined, // 医保对码标记
manufacturerId: undefined, // 厂家编码
supplyId: undefined, // 供应商编码
description: undefined, // 说明
jurisdiction: undefined, // 适用范围
ruleId: undefined, // 执行科室
substanceText: undefined, // 主要成分
allergenFlag: undefined, // 过敏标记
orgId: undefined, // 科室ID
locationId: undefined, // 地点ID
ybType: undefined, // 医保类型
itemTypeCode: undefined, // 最小收费
purchasePrice: undefined, // 购入价
retailPrice: undefined, // 零售价
maximumRetailPrice: undefined, // 最高零售价
chrgitmLv: undefined, // 医保等级
};
proxy.resetForm('deviceDialogRef');
}
/** 提交按钮 */
function submitForm() {
proxy.$refs['deviceDialogRef'].validate((valid) => {
if (valid) {
form.value.hvcmFlag ? (form.value.hvcmFlag = 1) : (form.value.hvcmFlag = 0);
form.value.ybFlag ? (form.value.ybFlag = 1) : (form.value.ybFlag = 0);
form.value.ybMatchFlag ? (form.value.ybMatchFlag = 1) : (form.value.ybMatchFlag = 0);
form.value.allergenFlag ? (form.value.allergenFlag = 1) : (form.value.allergenFlag = 0);
if (form.value.id != undefined) {
editDevice(form.value).then((response) => {
// 触发自定义事件,并传递数据给父组件
emits('submit');
proxy.$modal.msgSuccess('修改成功');
visible.value = false;
reset(); // 重置表单数据
});
} else {
addDevice(form.value).then((response) => {
// 触发自定义事件,并传递数据给父组件
emits('submit');
proxy.$modal.msgSuccess('新增成功');
visible.value = false;
reset(); // 重置表单数据
});
}
}
});
}
/** 包装单位搜索方法(支持拼音搜索) */
function handleUnitCodeSearch(query) {
if (query !== '') {
unitCodeLoading.value = true;
getDicts('unit_code', query).then(response => {
unitCodeOptions.value = response.data ? response.data.map(p => ({
label: p.dictLabel,
value: p.dictValue
})) : [];
unitCodeLoading.value = false;
}).catch(() => {
unitCodeOptions.value = [];
unitCodeLoading.value = false;
});
} else {
// 如果搜索关键词为空,加载全部数据
handleUnitCodeFocus();
}
}
/** 包装单位下拉框获得焦点时,加载全部数据 */
function handleUnitCodeFocus() {
unitCodeLoading.value = true;
getDicts('unit_code').then(response => {
unitCodeOptions.value = response.data ? response.data.map(p => ({
label: p.dictLabel,
value: p.dictValue
})) : [];
unitCodeLoading.value = false;
}).catch(() => {
unitCodeOptions.value = [];
unitCodeLoading.value = false;
});
}
/** 当用户选择包装单位时,销售单位和最小单位的值设置为与包装单位相同的值 */
function handleUnitCodeChange(value) {
form.value.salesUnitCode = value;
form.value.minUnitCode = value;
}
// 在这里可以根据购入价来更新零售价
function updatePrices(value) {
form.value.retailPrice = form.value.purchasePrice;
form.value.maximumRetailPrice = form.value.purchasePrice;
}
function formatValue(str) {
if (str === null || str === undefined || str === '' || str === 'null') {
return undefined;
}
return str;
}
/** 取消按钮 */
function cancel() {
visible.value = false;
reset();
}
defineExpose({
show,
edit,
setValue,
});
</script>
<style scoped>
.el-form--inline .el-form-item {
display: inline-flex;
vertical-align: middle;
margin-right: 10px !important;
}
/* 使用深度选择器 */
.custom-label-spacing :deep(.el-form-item__label) {
line-height: 1.2; /* 调整行间距 */
margin-bottom: 4px; /* 调整 label 和输入框之间的间距 */
}
</style>