feat(organization): 支持科室分类多选功能

- 修改前端界面组件支持科室分类多选下拉框
- 更新后端接口参数类型从Integer改为String以支持多选值
- 实现FIND_IN_SET查询方式处理多选分类条件
- 添加parseClassEnumValues函数处理字符串或数组格式转换
- 在医院住院对话框中扩展筛选条件支持多选分类
- 优化错误信息显示逻辑提供更详细的错误提示
- 在患者列表组件中添加入院日期和主治医生信息展示
- 修复多个服务调用中科室分类参数传递的数据类型问题
This commit is contained in:
2026-01-18 13:39:57 +08:00
parent 2fe6d45ad4
commit 59157fda56
19 changed files with 216 additions and 47 deletions

View File

@@ -93,6 +93,16 @@
</el-tag>
</div>
</div>
<!-- 添加入院日期等关键信息 -->
<div class="admission-info" v-if="item.admissionDate">
<span class="admission-date">入院日期{{ item.admissionDate }}</span>
</div>
<!-- 添加主治医生信息 -->
<div class="attending-doctor" v-if="item.attendingDoctorName">
<span class="doctor-name">主管医生{{ item.attendingDoctorName }}</span>
</div>
</div>
</div>
</div>
@@ -456,7 +466,9 @@ watch(
padding: 8px 12px 10px;
.personal-info-container {
display: block;
display: flex;
flex-direction: column;
gap: 4px;
.name-container {
display: flex;
@@ -469,6 +481,10 @@ watch(
color: #111827;
font-weight: 600;
font-size: 16px;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.age {
@@ -485,6 +501,19 @@ watch(
}
}
}
.admission-info, .attending-doctor {
display: flex;
font-size: 12px;
color: #6b7280;
margin-top: 2px;
.admission-date, .doctor-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}

View File

@@ -22,7 +22,7 @@
</el-select>
</el-form-item>
<el-form-item label="科室分类" prop="classEnum">
<el-select v-model="queryParams.classEnum" placeholder="请选择科室分类" clearable style="width: 200px">
<el-select v-model="queryParams.classEnum" placeholder="请选择科室分类" clearable multiple style="width: 200px">
<el-option
v-for="item in classEnumOption"
:key="item.value"
@@ -75,7 +75,21 @@
<el-table-column type="selection" width="55" />
<el-table-column label="科室名称" align="left" prop="name" />
<el-table-column label="科室类型" align="center" prop="typeEnum_dictText" />
<el-table-column label="科室分类" align="center" prop="classEnum_dictText" />
<el-table-column label="科室分类" align="center">
<template #default="scope">
<span v-if="scope.row.classEnum_dictText">
<el-tag
v-for="item in scope.row.classEnum_dictText.split(',')"
:key="item"
size="small"
style="margin-right: 2px;"
>
{{ item }}
</el-tag>
</span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column label="医保码" align="center" prop="ybNo" />
<el-table-column label="医保名称" align="center" prop="ybName" />
<el-table-column label="挂号科室" align="center">
@@ -154,6 +168,7 @@
v-model="form.classEnum"
placeholder="请选择科室分类"
clearable
multiple
style="width: 100%"
:disabled="form.typeEnum != 2"
>
@@ -342,17 +357,32 @@ function reset() {
// 从字典数据中查找对应的值,处理类型转换
function getDictLabel(value) {
if (!value || !organization_class.value || organization_class.value.length === 0) return '';
// 尝试进行类型转换比较,处理可能的字符串/数字不匹配问题
const stringValue = String(value);
const dict = organization_class.value.find(item => {
// 比较转换后的字符串值
return String(item.value) === stringValue;
});
return dict ? dict.label : '';
}
// 解析科室分类值,处理字符串或数组格式
function parseClassEnumValues(value) {
if (!value) return [];
if (Array.isArray(value)) {
return value.filter(item => item !== null && item !== undefined && item !== '');
} else if (typeof value === 'string') {
// 如果是逗号分隔的字符串,分割并过滤空值
return value.split(',').map(item => item.trim()).filter(item => item !== '');
} else {
// 如果是单个值,转换为字符串
return [String(value)].filter(item => item !== '');
}
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNo = 1;
@@ -375,14 +405,21 @@ function getPageList() {
const processedData = res.data.records.map(item => {
// 保留原有显示文本作为基础
const originalText = item.classEnum_dictText || '';
// 如果系统标准字典存在,尝试使用字典中的文本覆盖原有文本
if (organization_class.value && organization_class.value.length > 0) {
const dictLabel = getDictLabel(item.classEnum);
// 处理多选值的情况
let newText = '';
if (item.classEnum) {
// 如果classEnum是逗号分隔的字符串则处理每个值
const classEnumValues = parseClassEnumValues(item.classEnum);
const labels = classEnumValues.map(val => getDictLabel(val)).filter(label => label);
newText = labels.join(',');
}
// 只有在字典中找到匹配值时才替换,否则保留原有文本
return {
...item,
classEnum_dictText: dictLabel || originalText
classEnum_dictText: newText || originalText
};
}
return item;
@@ -423,8 +460,16 @@ function handelEdit(row) {
form.value.ybNo = orgInfo.ybNo;
form.value.ybName = orgInfo.ybName;
form.value.typeEnum = orgInfo.typeEnum;
// 确保科室分类值的类型正确,使其能正确匹配下拉选项中的值
form.value.classEnum = orgInfo.classEnum !== undefined ? String(orgInfo.classEnum) : undefined;
// 处理多选的科室分类,如果是逗号分隔的字符串则转换为数组
if (orgInfo.classEnum) {
if (typeof orgInfo.classEnum === 'string' && orgInfo.classEnum.includes(',')) {
form.value.classEnum = orgInfo.classEnum.split(',').map(item => item.trim());
} else {
form.value.classEnum = [String(orgInfo.classEnum)];
}
} else {
form.value.classEnum = [];
}
form.value.busNoParent = orgInfo.busNo.split('.').length > 1 ? orgInfo.busNo.split('.')[0] : undefined;
form.value.registerFlag = !!orgInfo.registerFlag;
form.value.location = orgInfo.location;
@@ -452,15 +497,16 @@ function submitForm() {
// 确保registerFlag从布尔值转换为整数true=1, false=0
formData.registerFlag = Number(formData.registerFlag ? 1 : 0);
// 确保classEnum字段有值数据库必填
// 处理多选的科室分类,如果是数组则转换为逗号分隔的字符串
if (Array.isArray(formData.classEnum)) {
formData.classEnum = formData.classEnum.length > 0 ? formData.classEnum.join(',') : null;
}
// 如果未定义设置默认值1
if (formData.classEnum === undefined || formData.classEnum === null || formData.classEnum === '') {
formData.classEnum = 1;
formData.classEnum = null;
}
// 确保classEnum为数字类型
formData.classEnum = Number(formData.classEnum);
// 验证提交数据
console.log('提交的数据:', formData);

View File

@@ -257,8 +257,11 @@ function openDialog() {
const flattenTree = (nodes) => {
let result = [];
nodes.forEach(node => {
// 检查当前节点是否符合条件
if (node && node.typeEnum === 2 && node.classEnum === 2) {
// 检查当前节点是否符合条件 - 扩展筛选条件
if (node &&
node.typeEnum === 2 && // 科室类型
checkClassEnumValue(node.classEnum, 2) && // 住院类别(支持多选)
node.activeFlag !== 0) { // 活跃状态(非停用)
result.push(node);
}
// 递归处理子节点
@@ -288,7 +291,9 @@ function openDialog() {
}).catch(error => {
console.error('获取组织机构数据失败:', error);
organization.value = [];
proxy.$modal.msgError('获取组织机构数据失败,请稍后重试');
// 显示详细的错误信息
const errorMessage = error.message || error.msg || '获取组织机构数据失败,请稍后重试';
proxy.$modal.msgError(errorMessage);
});
// 获取初始化数据
@@ -338,7 +343,9 @@ function handleNodeClick(orgInfo) {
console.error('获取病区列表失败:', error);
wardListOptions.value = [];
submitForm.wardLocationId = undefined;
proxy.$modal.msgError('获取病区列表失败,请稍后重试');
// 显示详细的错误信息
const errorMessage = error.message || error.msg || '获取病区列表失败,请稍后重试';
proxy.$modal.msgError(errorMessage);
});
} else {
wardListOptions.value = [];
@@ -402,13 +409,22 @@ function submit() {
}
}).catch(error => {
console.error('提交出错:', error);
let errorMsg = '提交请求失败';
// 构建详细的错误信息
let errorMsg = '办理住院过程中发生错误';
if (error.response) {
errorMsg += ` (${error.response.status}): ${error.response.data.message || error.response.statusText}`;
// 如果后端返回了具体错误信息,优先使用
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 += ': 网络请求失败,请检查网络连接';
errorMsg = '网络请求失败,请检查网络连接';
} else {
errorMsg += `: ${error.message}`;
errorMsg = error.message || errorMsg;
}
proxy.$modal.msgError(errorMsg);
}).finally(() => {
@@ -424,6 +440,20 @@ function submit() {
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>

View File

@@ -225,7 +225,7 @@ import {formatDate, formatDateStr} from '@/utils/index';
import useUserStore from '@/store/modules/user';
import {nextTick} from 'vue';
import {updatePatientInfo} from './components/store/patient.js';
import {ElMessage} from 'element-plus';
import {ElMessage, ElMessageBox} from 'element-plus';
// // 监听路由离开事件
// onBeforeRouteLeave((to, from, next) => {
@@ -707,9 +707,12 @@ const onHospitalization = async () => {
}
} catch (error) {
console.error('办理住院检查过程中发生错误:', error);
// 显示详细的错误信息
const errorMessage = error.message || error.msg || '办理住院过程中发生错误,请稍后重试!';
ElMessage({
type: 'error',
message: '办理住院过程中发生错误,请稍后重试!',
message: errorMessage,
duration: 5000 // 增加显示时长以便用户阅读
});
}
};

View File

@@ -426,7 +426,7 @@ function getInitOptions() {
getOrgList().then((res) => {
// organization.value = res.data.records
organization.value = res.data.records[0].children.filter(
(record) => record.typeEnum === 2 && record.classEnum === 2
(record) => record.typeEnum === 2 && checkClassEnumValue(record.classEnum, 2)
);
});
// if (!props.noFile) {
@@ -537,6 +537,21 @@ const init = () => {
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>

View File

@@ -195,7 +195,7 @@
<!-- 新增或修改手术对话框 -->
<el-dialog :title="title" v-model="open" width="800px" @close="cancel" append-to-body :close-on-click-modal="false">
<!-- 编辑模式下显示当前状态 -->
<!-- 编辑模式下显示当前状态 -->ElMessageBox is not defined
<el-alert v-if="isEditMode && form.statusEnum !== undefined" :title="'当前状态: ' + getStatusText(form.statusEnum)" :type="getStatusType(form.statusEnum)" :closable="false" style="margin-bottom: 20px;" />
<!-- 查看模式下显示提示 -->
<el-alert v-if="isViewMode" title="当前为查看模式,所有字段均为只读状态" type="info" :closable="false" style="margin-bottom: 20px;" />