- 引入watch监听诊断类别字典变化,动态设置默认值 - 移除硬编码的medTypeCode初始值'21',改为从字典动态获取 - 修复科室选择逻辑,支持当前医生科室不在住院科室列表时的显示 - 为诊断类别添加验证逻辑,确保主诊断的medTypeCode在字典选项中 - 解决已选科室不在过滤列表中时无法正确显示的问题 - 添加科室树形结构递归查找功能,支持临时添加医生科室到选项列表
530 lines
17 KiB
Vue
530 lines
17 KiB
Vue
<template>
|
||
<el-dialog
|
||
title="住院登记"
|
||
v-model="props.open"
|
||
width="1000px"
|
||
append-to-body
|
||
destroy-on-close
|
||
@close="close"
|
||
@open="openDialog"
|
||
>
|
||
<div class="operate">
|
||
<div>患者信息</div>
|
||
</div>
|
||
<el-row>
|
||
<el-col :span="2" class="descriptions-item-label">
|
||
<el-text truncated>患者姓名:</el-text>
|
||
</el-col>
|
||
<el-col :span="3" class="patInfo-value">
|
||
<el-text truncated>{{ patientInfo.patientName }}</el-text>
|
||
</el-col>
|
||
<el-col :span="2" class="descriptions-item-label">
|
||
<el-text truncated>年龄:</el-text>
|
||
</el-col>
|
||
<el-col :span="3" class="patInfo-value">
|
||
<el-text truncated>{{ patientInfo.age }}</el-text>
|
||
</el-col>
|
||
<el-col :span="2" class="descriptions-item-label">
|
||
<el-text truncated>性别:</el-text>
|
||
</el-col>
|
||
<el-col :span="3" class="patInfo-value">
|
||
<el-text truncated>{{ patientInfo.genderEnum_enumText }}</el-text>
|
||
</el-col>
|
||
<el-col :span="2" class="descriptions-item-label">
|
||
<el-text truncated>费用性质:</el-text>
|
||
</el-col>
|
||
<el-col :span="3" class="patInfo-value">
|
||
<el-text truncated>{{ patientInfo.contractName }}</el-text>
|
||
</el-col>
|
||
</el-row>
|
||
<div class="operate">
|
||
<div>住院信息</div>
|
||
</div>
|
||
<el-form
|
||
class="register-from"
|
||
:model="submitForm"
|
||
style="padding-left: 8px"
|
||
ref="registerRef"
|
||
label-width="80px"
|
||
:rules="rules"
|
||
>
|
||
<el-row :gutter="8">
|
||
<el-col :span="6">
|
||
<el-form-item label="入院科室" prop="inHospitalOrgId">
|
||
<el-tree-select
|
||
clearable
|
||
style="width: 100%"
|
||
v-model="submitForm.inHospitalOrgId"
|
||
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 v-model="submitForm.wardLocationId">
|
||
<el-option
|
||
v-for="item in wardListOptions"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="item.id"
|
||
/>
|
||
<template #empty>
|
||
<div>请先选择入院科室</div>
|
||
</template>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-col>
|
||
<el-col :span="6">
|
||
<el-form-item label="患者病情">
|
||
<el-select v-model="submitForm.priorityEnum">
|
||
<el-option
|
||
v-for="item in 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">
|
||
<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">
|
||
<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-row>
|
||
<el-row :gutter="8">
|
||
<el-col :span="6">
|
||
<el-form-item label="诊断类别" prop="medTypeCode">
|
||
<el-select
|
||
v-model="submitForm.medTypeCode"
|
||
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="12">
|
||
<el-form-item label="入院诊断" prop="diagnosisDefinitionId">
|
||
<!-- <el-select
|
||
v-model="submitForm.diagnosisDefinitionId"
|
||
placeholder="诊断"
|
||
clearable
|
||
filterable
|
||
remote
|
||
:remote-method="getDiagnosisInfo"
|
||
style="width: 400px"
|
||
>
|
||
<el-option
|
||
v-for="item in diagnosisDefinitionList"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="item.id"
|
||
@click="handleDiagnosisChange(item)"
|
||
/>
|
||
</el-select> -->
|
||
<el-input v-model="props.mainDiagnosis.name" disabled style="width: 400px" />
|
||
<!-- 隐藏存储ID的字段 -->
|
||
<input type="hidden" v-model="submitForm.diagnosisDefinitionId" />
|
||
</el-form-item>
|
||
</el-col>
|
||
</el-row>
|
||
</el-form>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button type="primary" @click="submit">确 定</el-button>
|
||
<el-button @click="close">取 消</el-button>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup>
|
||
import {watch} from 'vue';
|
||
import {getDiagnosisDefinitionList, getInit, getOrgList, handleHospitalization, wardList,} from './api.js';
|
||
|
||
const submitForm = reactive({
|
||
medTypeCode: '', // 从字典动态获取默认值
|
||
});
|
||
|
||
const props = defineProps({
|
||
open: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
patientInfo: {
|
||
type: Object,
|
||
default: () => ({}),
|
||
},
|
||
encounterId: {
|
||
type: String,
|
||
default: '',
|
||
},
|
||
mainDiagnosis: { type: Object, default: null },
|
||
});
|
||
const emit = defineEmits(['close']);
|
||
|
||
const priorityLevelOptionOptions = ref(undefined);
|
||
const organization = ref([]);
|
||
const wardListOptions = ref([]);
|
||
const diagnosisDefinitionList = ref([]);
|
||
let diagnosisDefinitionId = '';
|
||
let diagnosisYbNo = '';
|
||
|
||
const { proxy } = getCurrentInstance();
|
||
|
||
const { med_type } = proxy.useDict('med_type');
|
||
|
||
// 监听诊断类别字典加载,默认选择第一项(仅当没有主诊断时)
|
||
watch(
|
||
med_type,
|
||
(newVal) => {
|
||
if (newVal && newVal.length > 0 && !submitForm.medTypeCode && !props.mainDiagnosis) {
|
||
submitForm.medTypeCode = newVal[0].value;
|
||
}
|
||
},
|
||
{ immediate: true }
|
||
);
|
||
const rules = reactive({
|
||
diagnosisDefinitionId: [
|
||
{
|
||
required: true,
|
||
message: '入院诊断未填写',
|
||
trigger: ['blur', 'change'],
|
||
},
|
||
],
|
||
medTypeCode: [
|
||
{
|
||
required: true,
|
||
message: '诊断类别未选择',
|
||
trigger: ['blur', 'change'],
|
||
},
|
||
],
|
||
inHospitalOrgId: [
|
||
{
|
||
required: true,
|
||
message: '入院科室未填写',
|
||
trigger: ['blur', 'change'],
|
||
},
|
||
],
|
||
});
|
||
|
||
function openDialog() {
|
||
console.log('hospitalizationDialog openDialog 被调用');
|
||
console.log('props.patientInfo:', props.patientInfo);
|
||
console.log('props.encounterId:', props.encounterId);
|
||
console.log('props.patientInfo.encounterId:', props.patientInfo?.encounterId);
|
||
console.log('orgId==========>', props.patientInfo.orgId);
|
||
|
||
getOrgList().then((res) => {
|
||
console.log('获取组织机构数据:', res);
|
||
|
||
// 确保数据结构正确
|
||
if (res && res.code === 200 && res.data && res.data.records && Array.isArray(res.data.records)) {
|
||
// 递归遍历树形结构,获取所有符合条件的节点
|
||
const flattenTree = (nodes) => {
|
||
let result = [];
|
||
nodes.forEach(node => {
|
||
// 检查当前节点是否符合条件 - 扩展筛选条件
|
||
if (node &&
|
||
node.typeEnum === 2 && // 科室类型
|
||
checkClassEnumValue(node.classEnum, 2) && // 住院类别(支持多选)
|
||
node.activeFlag !== 0) { // 活跃状态(非停用)
|
||
result.push(node);
|
||
}
|
||
// 递归处理子节点
|
||
if (node.children && Array.isArray(node.children)) {
|
||
result = result.concat(flattenTree(node.children));
|
||
}
|
||
});
|
||
return result;
|
||
};
|
||
|
||
// 从树形结构中提取所有符合条件的组织
|
||
organization.value = flattenTree(res.data.records);
|
||
|
||
console.log('筛选后的组织机构数据:', organization.value);
|
||
|
||
// 默认选中当前医生所在科室(即使不在住院科室列表中)
|
||
if (props.patientInfo?.orgId) {
|
||
const doctorOrgId = props.patientInfo.orgId;
|
||
const exists = organization.value.some((item) => item?.id === doctorOrgId);
|
||
|
||
if (exists) {
|
||
// 如果医生科室在列表中,直接选中
|
||
submitForm.inHospitalOrgId = doctorOrgId;
|
||
} else {
|
||
// 如果医生科室不在列表中(如门诊科室),临时添加到列表并选中
|
||
// 从原始数据中找到医生科室信息
|
||
const findOrgInTree = (nodes, orgId) => {
|
||
for (const node of nodes) {
|
||
if (node.id === orgId) return node;
|
||
if (node.children) {
|
||
const found = findOrgInTree(node.children, orgId);
|
||
if (found) return found;
|
||
}
|
||
}
|
||
return null;
|
||
};
|
||
const doctorOrg = findOrgInTree(res.data.records, doctorOrgId);
|
||
if (doctorOrg) {
|
||
organization.value.unshift(doctorOrg);
|
||
submitForm.inHospitalOrgId = doctorOrgId;
|
||
}
|
||
}
|
||
|
||
// 触发科室选择事件,加载对应病区
|
||
if (submitForm.inHospitalOrgId) {
|
||
handleNodeClick({ id: submitForm.inHospitalOrgId });
|
||
}
|
||
}
|
||
} else {
|
||
organization.value = [];
|
||
console.warn('获取组织机构数据为空或格式不正确:', res);
|
||
}
|
||
|
||
console.log('organization==========>', organization.value);
|
||
}).catch(error => {
|
||
console.error('获取组织机构数据失败:', error);
|
||
organization.value = [];
|
||
// 显示详细的错误信息
|
||
const errorMessage = error.message || error.msg || '获取组织机构数据失败,请稍后重试';
|
||
proxy.$modal.msgError(errorMessage);
|
||
});
|
||
|
||
// 获取初始化数据
|
||
getInit().then((response) => {
|
||
console.log(response, 'response');
|
||
if (response.data && response.data.priorityLevelOptionOptions) {
|
||
priorityLevelOptionOptions.value = response.data.priorityLevelOptionOptions; // 优先级
|
||
}
|
||
});
|
||
console.log(props.patientInfo, 'patientInfo');
|
||
getDiagnosisInfo(undefined);
|
||
console.log(props.mainDiagnosis, 'mainDiagnosis');
|
||
if (props.mainDiagnosis) {
|
||
submitForm.diagnosisDefinitionId = props.mainDiagnosis.definitionId;
|
||
diagnosisDefinitionId = props.mainDiagnosis.definitionId;
|
||
diagnosisYbNo = props.mainDiagnosis.ybNo || '';
|
||
submitForm.diagnosisDesc = props.mainDiagnosis.name || ''; // 设置诊断描述
|
||
diagnosisDefinitionList.value = [props.mainDiagnosis];
|
||
|
||
// 诊断类别:优先使用主诊断的medTypeCode,但要验证是否在字典选项中
|
||
const diagnosisMedTypeCode = props.mainDiagnosis.medTypeCode;
|
||
const medTypeExists = med_type.value && med_type.value.some(item => item.value === diagnosisMedTypeCode);
|
||
if (medTypeExists) {
|
||
submitForm.medTypeCode = diagnosisMedTypeCode;
|
||
} else if (med_type.value && med_type.value.length > 0) {
|
||
// 如果主诊断的medTypeCode不在字典中,默认选择字典第一项
|
||
submitForm.medTypeCode = med_type.value[0].value;
|
||
}
|
||
} else if (med_type.value && med_type.value.length > 0) {
|
||
// 无主诊断时,默认选择字典第一项
|
||
submitForm.medTypeCode = med_type.value[0].value;
|
||
}
|
||
}
|
||
|
||
function getDiagnosisInfo(value) {
|
||
getDiagnosisDefinitionList({ pageSize: 500, pageNo: 1, searchKey: value }).then((res) => {
|
||
diagnosisDefinitionList.value = res.data.records;
|
||
});
|
||
}
|
||
|
||
function handleDiagnosisChange(item) {
|
||
diagnosisYbNo = item.ybNo;
|
||
diagnosisDefinitionId = item.id;
|
||
}
|
||
|
||
function handleNodeClick(orgInfo) {
|
||
// 确保传入正确的科室ID
|
||
if (orgInfo && orgInfo.id) {
|
||
wardList({ orgId: orgInfo.id }).then((res) => {
|
||
if (res && res.data) {
|
||
wardListOptions.value = res.data;
|
||
// 清空之前选择的病区
|
||
submitForm.wardLocationId = undefined;
|
||
} else {
|
||
wardListOptions.value = [];
|
||
submitForm.wardLocationId = undefined;
|
||
}
|
||
}).catch(error => {
|
||
console.error('获取病区列表失败:', error);
|
||
wardListOptions.value = [];
|
||
submitForm.wardLocationId = undefined;
|
||
// 显示详细的错误信息
|
||
const errorMessage = error.message || error.msg || '获取病区列表失败,请稍后重试';
|
||
proxy.$modal.msgError(errorMessage);
|
||
});
|
||
} else {
|
||
wardListOptions.value = [];
|
||
submitForm.wardLocationId = undefined;
|
||
}
|
||
}
|
||
|
||
function handleChange(value) {
|
||
if (!value) {
|
||
wardListOptions.value = [];
|
||
submitForm.wardLocationId = undefined;
|
||
} else {
|
||
// 当选择新科室时,清空病区选择
|
||
submitForm.wardLocationId = undefined;
|
||
}
|
||
}
|
||
|
||
function submit() {
|
||
console.log('hospitalizationDialog submit 被调用');
|
||
console.log('props.patientInfo:', props.patientInfo);
|
||
console.log('props.encounterId:', props.encounterId);
|
||
console.log('props.patientInfo.encounterId:', props.patientInfo?.encounterId);
|
||
|
||
proxy.$refs['registerRef'].validate((valid) => {
|
||
if (valid) {
|
||
// 验证必要字段
|
||
if (!props.patientInfo.patientId) {
|
||
console.log('患者信息不完整,缺少 patientId');
|
||
proxy.$modal.msgError('患者信息不完整,无法办理住院');
|
||
return;
|
||
}
|
||
|
||
if (!props.encounterId && !props.patientInfo.encounterId) {
|
||
console.log('就诊信息不完整,缺少 encounterId');
|
||
proxy.$modal.msgError('就诊信息不完整,无法办理住院');
|
||
return;
|
||
}
|
||
|
||
let saveData = {
|
||
...submitForm,
|
||
diagnosisYbNo: diagnosisYbNo,
|
||
diagnosisDefinitionId: diagnosisDefinitionId,
|
||
// 优先使用props.encounterId,确保就诊ID正确传递
|
||
ambEncounterId: props.encounterId || props.patientInfo.encounterId,
|
||
patientId: props.patientInfo.patientId,
|
||
};
|
||
|
||
console.log('提交住院数据:', saveData);
|
||
|
||
// 显示加载状态
|
||
const loading = proxy.$modal.loading('正在办理住院...');
|
||
|
||
handleHospitalization(saveData).then((res) => {
|
||
console.log('住院办理API响应:', res);
|
||
if (res.code == 200) {
|
||
proxy.$modal.msgSuccess('办理成功');
|
||
close();
|
||
} else {
|
||
console.error('办理失败:', res.msg);
|
||
proxy.$modal.msgError(res.msg || '办理失败,请检查数据后重试');
|
||
}
|
||
}).catch(error => {
|
||
console.error('提交出错:', error);
|
||
// 构建详细的错误信息
|
||
let errorMsg = '办理住院过程中发生错误';
|
||
if (error.response) {
|
||
// 如果后端返回了具体错误信息,优先使用
|
||
if (error.response.data && error.response.data.message) {
|
||
errorMsg = error.response.data.message;
|
||
} else if (error.response.data) {
|
||
// 如果响应体中有其他可读信息
|
||
errorMsg = typeof error.response.data === 'string' ? error.response.data : `${errorMsg} (${error.response.status})`;
|
||
} else {
|
||
errorMsg = `${errorMsg} (${error.response.status}): ${error.response.statusText}`;
|
||
}
|
||
} else if (error.request) {
|
||
errorMsg = '网络请求失败,请检查网络连接';
|
||
} else {
|
||
errorMsg = error.message || errorMsg;
|
||
}
|
||
proxy.$modal.msgError(errorMsg);
|
||
}).finally(() => {
|
||
// 关闭加载状态
|
||
proxy.$modal.closeLoading();
|
||
});
|
||
} else {
|
||
console.log('表单验证失败');
|
||
}
|
||
});
|
||
}
|
||
|
||
function close() {
|
||
emit('close');
|
||
}
|
||
|
||
// 检查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;
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.operate {
|
||
font-size: 16px;
|
||
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: 10px 0;
|
||
}
|
||
|
||
.patInfo-value {
|
||
width: 100px;
|
||
}
|
||
</style>
|