Files
his/openhis-ui-vue3/src/views/inHospitalManagement/charge/register/components/registerForm.vue
chenqi 59157fda56 feat(organization): 支持科室分类多选功能
- 修改前端界面组件支持科室分类多选下拉框
- 更新后端接口参数类型从Integer改为String以支持多选值
- 实现FIND_IN_SET查询方式处理多选分类条件
- 添加parseClassEnumValues函数处理字符串或数组格式转换
- 在医院住院对话框中扩展筛选条件支持多选分类
- 优化错误信息显示逻辑提供更详细的错误提示
- 在患者列表组件中添加入院日期和主治医生信息展示
- 修复多个服务调用中科室分类参数传递的数据类型问题
2026-01-18 13:39:57 +08:00

584 lines
17 KiB
Vue
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>
<div class="registerForm-container">
<div class="operate">
<div>住院信息</div>
</div>
<el-form
class="register-from"
:model="submitForm"
style="padding-left: 8px"
ref="registerRef"
label-width="80px"
:rules="rules"
:disabled="props.isRegistered"
>
<el-row :gutter="8">
<el-col :span="6">
<el-form-item label="住院号:" prop="encounterBusNo">
{{ submitForm.busNo ? submitForm.busNo : '-' }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="住院次数:" prop="hospitalizationCount" autocomplete="off">
{{ submitForm.inHospitalCount }}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院科室" prop="inHospitalOrgId">
<el-tree-select
clearable
style="width: 100%"
v-model="submitForm.inHospitalOrgId"
:disabled="props.isRegistered"
filterable
:data="organization"
:props="{
value: 'id',
label: 'name',
children: 'children',
}"
value-key="id"
check-strictly
:check-strictly-except-leaf="false"
:default-expand-all="true"
placeholder="请选择入院科室"
@change="handleChange"
@node-click="handleNodeClick"
/>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院病区" prop="wardLocationId">
<el-select
:disabled="props.isRegistered || !submitForm.inHospitalOrgId"
v-model="submitForm.wardLocationId"
placeholder="请先选择入院科室"
>
<el-option
v-for="item in wardListOptions"
:key="item.id"
:label="item.name"
:value="item.id"
@click="handleWardClick(item)"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="床位数:" prop="bedCount">
{{
submitForm.totalBedsNum ? submitForm.idleBedsNum + '/' + submitForm.totalBedsNum : '-'
}}
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="门诊医生" prop="ambDoctorPractitionerName">
<el-input disabled v-model="submitForm.ambDoctorPractitionerName" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="诊断类别" prop="medTypeCode">
<el-select
v-model="submitForm.medTypeCode"
:disabled="props.isRegistered"
placeholder="诊断类别"
clearable
filterable
@change="
(value) => {
submitForm.ybClassEnum = value;
}
"
>
<el-option
v-for="item in med_type"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6" v-if="!props.noFile">
<el-form-item label="入院诊断" prop="ambDiagnosisName">
<el-input v-model="submitForm.ambDiagnosisName" disabled />
</el-form-item>
</el-col>
<el-col :span="6" v-else>
<el-form-item label="入院诊断" prop="diagnosisDefinitionId">
<el-select
v-model="submitForm.diagnosisDefinitionId"
:disabled="props.isRegistered"
placeholder="入院诊断"
clearable
filterable
remote
:remote-method="getDiagnosisInfo"
>
<el-option
v-for="item in diagnosisDefinitionList"
:key="item.id"
:label="item.name"
:value="item.id"
@click="handleDiagnosisChange(item)"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6" v-if="props.noFile">
<el-form-item label="诊断描述" prop="diagnosisDesc">
<el-input v-model="submitForm.diagnosisDesc" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="患者病情">
<el-select v-model="submitForm.priorityEnum" :disabled="props.isRegistered">
<el-option
v-for="item in props.initOptions.priorityLevelOptionOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院类型" prop="admitSourceCode">
<el-select v-model="submitForm.admitSourceCode" :disabled="props.isRegistered">
<el-option
v-for="item in admit_source_code"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院方式" prop="inWayCode">
<el-select v-model="submitForm.inWayCode" :disabled="props.isRegistered">
<el-option
v-for="item in in_way_code"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="费用性质">
<el-select
v-model="submitForm.contractNo"
placeholder="费用性质"
clearable
:disabled="props.isRegistered"
@change="getValue"
>
<el-option
v-for="item in contractList"
:key="item.busNo"
:label="item.contractName"
:value="item.busNo"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="入院日期" prop="startTime">
<el-date-picker
v-model="submitForm.startTime"
:disabled="props.isRegistered"
value-format="YYYY-MM-DD HH:mm:ss"
type="date"
placeholder="请选择日期"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script setup>
import {
diagnosisInit,
getBedInfo,
getContractList,
getDiagnosisDefinitionList,
getOrgList,
getProvincesAndCities,
wardList,
} from './api';
import {formatDateStr} from '@/utils';
const { proxy } = getCurrentInstance();
const { in_way_code, admit_source_code, med_type } = proxy.useDict(
'in_way_code',
'admit_source_code',
'med_type'
);
const emits = defineEmits([]);
const props = defineProps({
patientInfo: {
type: Object,
require: true,
default: () => ({}),
},
inHospitalInfo: {
type: Object,
require: true,
default: () => ({}),
},
initOptions: {
type: Object,
require: true,
default: () => ({}),
},
isRegistered: {
type: Boolean,
default: false,
},
noFile: {
type: Boolean,
default: false,
},
});
const organization = ref([]);
const wardListOptions = ref([]);
const contractList = ref([]);
const verificationStatusOptions = ref([]);
const diagnosisDefinitionList = ref([]);
const wardLoading = ref(false);
const rules = reactive({
inHospitalOrgId: [
{
required: true,
message: '入院科室未填写',
trigger: ['blur', 'change'],
},
],
wardLocationId: [
{
required: true,
message: '入院病区未填写',
trigger: ['blur', 'change'],
},
],
startTime: [
{
required: true,
message: '入院日期未填写',
trigger: ['blur', 'change'],
},
],
diagnosisDefinitionId: [
{
required: true,
message: '入院诊断未填写',
trigger: ['blur', 'change'],
},
],
// diagnosisDesc: [
// {
// required: true,
// message: '诊断描述未填写',
// trigger: ['blur', 'change'],
// },
// ],
});
//获取省市医保字符串
const medicalInsuranceTitle = ref('');
// 暴露给父组件使用
// defineExpose({
// medicalInsuranceTitle,
// });
const getProvincesAndCitiesInfo = async () => {
try {
if (inHospitalInfo.encounterId) {
const res = await getProvincesAndCities(props.inHospitalInfo.encounterId);
// console.log('获取省市医保字符串', res);
if (res && res.code == 200) {
// 确保有数据时才更新
medicalInsuranceTitle.value = res.data?.insutype || res.data || '';
}
}
} catch (error) {
// 静默处理错误,确保页面不会显示错误信息
console.error('获取医保省市信息失败:', error);
}
};
onMounted(() => {
getProvincesAndCitiesInfo();
});
// 监听inHospitalInfo.encounterId的变化在弹窗打开时重新调用接口
watch(
() => props.inHospitalInfo.encounterId,
(newEncounterId) => {
if (newEncounterId) {
getProvincesAndCitiesInfo();
}
},
{ immediate: true }
);
/* 提交表单 */
const submitForm = reactive({
inHospitalOrgId: props.inHospitalInfo.inHospitalOrgId,
ambDoctorPractitionerName: props.inHospitalInfo.ambDoctorPractitionerName,
wardLocationId: props.inHospitalInfo.wardLocationId, // 入院护理组编码
admitSourceCode: '', // 患者入院类型字典PatientSource
inWayCode: '', // 入院方式字典InpWay
startTime: formatDateStr(new Date(), 'YYYY-MM-DD HH:mm:ss'), // 入院日期
priorityEnum: props.inHospitalInfo.priorityEnum, // 患者病情字典PatAdmCondition
ambDiagnosisName: props.inHospitalInfo.ambDiagnosisName,
medTypeCode: '21',
});
// /* 科室 病区 */
// watch(
// () => submitForm.inDocterWorkGroupCode,
// (newValue) => {
// if (newValue) {
// if (newValue == '') {
// submitForm.wardLocationId = '';
// }
// } else {
// submitForm.wardLocationId = '';
// }
// }
// );
// watch(
// () => submitForm.inNurseDeptCode,
// (newValue) => {
// if (newValue) {
// getBedInfo(newValue);
// }
// }
// );
watch(
() => submitForm.wardLocationId,
(newWardId) => {
if (newWardId && wardListOptions.value.length > 0) {
const selectedWard = wardListOptions.value.find((item) => item.id === newWardId);
if (selectedWard) {
handleWardClick(selectedWard);
}
} else {
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
}
},
{ immediate: true }
);
watch(
() => props.isRegistered,
(newVal) => {
if (newVal) {
// 已登记状态可以做一些数据锁定操作
} else {
init();
}
}
);
onMounted(() => {
getInitOptions();
setValue();
setDefaultAdmitSource();
if (submitForm.inHospitalOrgId) {
handleNodeClick({ id: submitForm.inHospitalOrgId });
}
});
const setDefaultAdmitSource = () => {
if (props.noFile) return;
const defaultItem = admit_source_code.value.find((item) => item.value === '1');
if (defaultItem) {
submitForm.admitSourceCode = props.inHospitalInfo?.admitSourceCode || defaultItem.value;
}
};
function handleWardClick(item) {
submitForm.wardBusNo = item.busNo;
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
getBedInfo(submitForm.wardBusNo)
.then((res) => {
if (res.data) {
submitForm.totalBedsNum = res.data.totalBedsNum;
submitForm.idleBedsNum = res.data.idleBedsNum;
} else {
submitForm.totalBedsNum = 0;
submitForm.idleBedsNum = 0;
}
})
.catch((err) => {
console.error('查询病床失败:', err);
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
});
}
function getInitOptions() {
getOrgList().then((res) => {
// organization.value = res.data.records
organization.value = res.data.records[0].children.filter(
(record) => record.typeEnum === 2 && checkClassEnumValue(record.classEnum, 2)
);
});
// if (!props.noFile) {
// wardList().then((res) => {
// wardListOptions.value = res.data;
// });
// }
diagnosisInit().then((res) => {
verificationStatusOptions.value = res.data.verificationStatusOptions;
});
getContractList().then((response) => {
contractList.value = response.data;
setValue();
});
getDiagnosisInfo(undefined);
}
function getDiagnosisInfo(value) {
getDiagnosisDefinitionList({ pageSize: 500, pageNo: 1, searchKey: value }).then((res) => {
diagnosisDefinitionList.value = res.data.records;
});
}
function handleNodeClick(orgInfo) {
submitForm.wardLocationId = undefined; // 切换科室时,先清空原有病区
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
wardListOptions.value = []; // 先清空列表,避免旧数据残留
wardLoading.value = true;
wardList({ orgId: orgInfo.id })
.then((res) => {
wardListOptions.value = res.data || [];
if (wardListOptions.value.length > 0 && !props.inHospitalInfo.wardLocationId) {
submitForm.wardLocationId = wardListOptions.value[0].id;
const defaultWard = wardListOptions.value.find(
(item) => item.id === submitForm.wardLocationId
);
if (defaultWard) {
handleWardClick(defaultWard);
}
}
})
.catch((err) => {
console.error('加载病区失败:', err);
wardListOptions.value = [];
})
.finally(() => {
wardLoading.value = false;
});
}
function handleChange(value) {
if (!value) {
wardListOptions.value = [];
submitForm.wardLocationId = undefined;
submitForm.totalBedsNum = undefined;
submitForm.idleBedsNum = undefined;
wardLoading.value = false; // 同步停止加载
}
}
function handleDiagnosisChange(item) {
submitForm.diagnosisYbNo = item.ybNo;
submitForm.diagnosisDefinitionId = item.id;
}
function setValue() {
submitForm.encounterId = props.inHospitalInfo?.encounterId;
submitForm.busNo = props.inHospitalInfo?.busNo;
submitForm.contractNo = props.inHospitalInfo?.contractNo;
submitForm.inHospitalCount = props.inHospitalInfo?.inHospitalCount;
submitForm.inHospitalOrgId = props.inHospitalInfo?.inHospitalOrgId;
submitForm.inHospitalOrgName = props.inHospitalInfo?.inHospitalOrgName;
submitForm.wardLocationId = props.inHospitalInfo?.wardLocationId;
submitForm.wardName = props.inHospitalInfo?.wardName;
submitForm.wardBusNo = props.inHospitalInfo?.wardBusNo;
submitForm.totalBedsNum = props.inHospitalInfo?.totalBedsNum;
submitForm.idleBedsNum = props.inHospitalInfo?.idleBedsNum;
submitForm.ambEncounterId = props.inHospitalInfo?.ambEncounterId;
submitForm.ambDoctorPractitionerId = props.inHospitalInfo?.ambDoctorPractitionerId;
submitForm.ambDoctorPractitionerName = props.inHospitalInfo?.ambDoctorPractitionerName;
submitForm.ambDiagnosisName = props.inHospitalInfo?.ambDiagnosisName;
submitForm.priorityEnum = props.inHospitalInfo?.priorityEnum;
submitForm.priorityEnum_enumText = props.inHospitalInfo?.priorityEnum_enumText;
// submitForm.admitSourceCode = props.inHospitalInfo?.admitSourceCode;
submitForm.admitSourceCode_dictText = props.inHospitalInfo?.admitSourceCode_dictText;
submitForm.inWayCode = props.inHospitalInfo?.inWayCode;
submitForm.inWayCode_dictText = props.inHospitalInfo?.inWayCode_dictText;
}
const registerRef = ref();
/* 登记 */
const validateData = async (callback) => {
if (!registerRef.value) return false;
registerRef.value.validate((valid) => {
if (valid) {
callback();
return true;
} else {
return false;
}
});
};
const init = () => {
if (!props.isRegistered) {
// 只有待登记状态才重置
submitForm.inDocterWorkGroupCode = '';
submitForm.wardLocationId = '';
}
};
// 检查classEnum值是否包含指定值支持多选
function checkClassEnumValue(classEnum, targetValue) {
if (!classEnum) return false;
// 如果是字符串且包含逗号,说明是多选值
if (typeof classEnum === 'string' && classEnum.includes(',')) {
const values = classEnum.split(',').map(v => v.trim());
return values.some(v => v == targetValue);
}
// 单个值的情况
return classEnum == targetValue;
}
defineExpose({ validateData, submitForm, init, medicalInsuranceTitle });
</script>
<style lang="scss" scoped>
.registerForm-container {
margin-top: 16px;
.operate {
background: rgba(37, 109, 149, 0.05);
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
border-radius: 4px 4px 0px 0px;
padding-left: 16px;
color: var(--hip-color-primary-light);
font-weight: bold;
margin-bottom: 8px;
}
.register-from {
padding: 0 8px;
}
:deep(.el-form-item) {
width: 100%;
margin-right: 0px;
}
}
</style>