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

478 lines
15 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>
<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 {getDiagnosisDefinitionList, getInit, getOrgList, handleHospitalization, wardList,} from './api.js';
const submitForm = reactive({
medTypeCode: '21',
});
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');
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) {
submitForm.inHospitalOrgId =
organization.value.find((item) => item?.id === props.patientInfo.orgId)?.id || '';
}
} 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.medTypeCode = props.mainDiagnosis.medTypeCode;
submitForm.diagnosisDesc = props.mainDiagnosis.name || ''; // 设置诊断描述
diagnosisDefinitionList.value = [props.mainDiagnosis];
}
}
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>