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

584 lines
20 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="app-container">
<!-- 查询表单 -->
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" class="query-form">
<el-form-item label="科室名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入科室名称"
clearable
@keyup.enter="handleQuery"
style="width: 200px"
/>
</el-form-item>
<el-form-item label="科室类型" prop="typeEnum">
<el-select v-model="queryParams.typeEnum" placeholder="请选择科室类型" clearable style="width: 200px">
<el-option
v-for="item in orgTypeOption"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="科室分类" prop="classEnum">
<el-select v-model="queryParams.classEnum" placeholder="请选择科室分类" clearable multiple style="width: 200px">
<el-option
v-for="item in classEnumOption"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item class="search-buttons">
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd"> 新增 </el-button>
</el-col>
<el-col :span="1.5">
<el-tooltip
:content="selectRowIds.length == 0 ? '至少选择一条数据' : ''"
placement="top"
:disabled="selectRowIds.length != 0"
>
<el-button
type=""
plain
icon="Delete"
:disabled="selectRowIds.length == 0"
@click="handleDelete"
>删除</el-button
>
</el-tooltip>
</el-col>
<el-col :span="1.5">
<el-button type="" plain icon="Download" @click="handleExport"> 导出 </el-button>
</el-col>
<el-col :span="1.5">
<el-button type="" plain icon="Refresh" @click="getPageList">刷新</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table
ref="orgTableRef"
v-loading="loading"
:data="organization"
row-key="id"
@selection-change="handleSelectionChange"
>
<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">
<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">
<template #default="scope">
{{ scope.row.registerFlag ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="科室位置" align="center" prop="location" show-overflow-tooltip />
<el-table-column label="科室简介" align="center" prop="intro" show-overflow-tooltip />
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column label="状态" align="center" prop="activeFlag_dictText" />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button link type="primary" @click="handelEdit(scope.row)">编辑</el-button>
<el-button
link
type="primary"
@click="handleDisabled(scope.row.id)"
v-if="scope.row.activeFlag == '1'"
>停用</el-button
>
<el-button link type="primary" @click="handelEnable(scope.row.id)" v-else>启用</el-button>
<el-button link type="primary" @click="handleAddInferior(scope.row)">
添加下级
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination-container">
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getPageList"
/>
</div>
<!-- 添加或修改参数配置对话框 -->
<el-dialog :title="title" v-model="open" width="600px" @close="cancel" append-to-body>
<el-form ref="orgRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="id" prop="id" v-show="false">
<el-input v-model="form.id" placeholder="请输入科室编号" />
</el-form-item>
<el-form-item label="科室编号" prop="busNo" v-show="false">
<el-input v-model="form.busNo" placeholder="请输入科室编号" />
</el-form-item>
<el-form-item label="科室名称" prop="name">
<el-input v-model="form.name" placeholder="请输入科室名称" />
</el-form-item>
<el-form-item label="医保码" prop="name">
<el-input v-model="form.ybNo" placeholder="请输入医保码" />
</el-form-item>
<el-form-item label="医保名称" prop="name">
<el-input v-model="form.ybName" placeholder="请输入医保名称" />
</el-form-item>
<el-form-item label="科室类型" prop="typeEnum">
<el-select
v-model="form.typeEnum"
placeholder="请选择科室类型"
clearable
style="width: 100%"
>
<el-option
v-for="item in orgTypeOption"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="科室分类" prop="classEnum">
<el-select
v-model="form.classEnum"
placeholder="请选择科室分类"
clearable
multiple
style="width: 100%"
:disabled="form.typeEnum != 2"
>
<el-option
v-for="item in classEnumOption"
:key="item.value"
:label="item.info"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-col>
<el-form-item label="上级科室" prop="busNoParent">
<el-tree-select
clearable
style="width: 100%"
v-model="form.busNoParent"
:data="organization"
:props="{ value: 'busNo', label: 'name', children: 'children' }"
value-key="id"
check-strictly
/>
</el-form-item>
</el-col>
<el-form-item label="挂号科室" prop="registerFlag">
<el-radio-group v-model="form.registerFlag" size="large">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="科室位置" prop="location">
<el-input v-model="form.location" placeholder="请输入科室位置" maxlength="100" show-word-limit />
</el-form-item>
<el-form-item label="科室简介" prop="intro">
<el-input
v-model="form.intro"
type="textarea"
placeholder="请输入科室简介"
maxlength="500"
show-word-limit
:rows="4"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入备注信息"
maxlength="1000"
show-word-limit
:rows="3"
/>
</el-form-item>
</el-form>
<template #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="Organization">
import {
addOrganization,
deleteOrganization,
disableOrg,
enableOrg,
getList,
getOrgDetail,
initOrgTypeOption,
updateOrganization
} from './components/api';
const { proxy } = getCurrentInstance();
const loading = ref(true);
const showSearch = ref(true);
const organization = ref([]);
const queryParams = ref({
pageNo: 1,
pageSize: 10,
name: undefined,
typeEnum: undefined,
classEnum: undefined
});
const open = ref(false);
const form = ref({
id: undefined,
busNo: undefined,
name: undefined,
typeEnum: undefined,
busNoParent: undefined,
registerFlag: false, // 挂号科室标记
location: undefined, // 科室位置
intro: undefined, // 科室简介
remark: undefined, // 备注
});
const orgTableRef = ref();
const orgRef = ref();
const orgTypeOption = ref([]);
const classEnumOption = ref([]);
const selectRowIds = ref([]);
const total = ref(0);
const title = ref('');
const rules = ref({
busNo: [{ required: false, message: '请输入科室编号', trigger: 'input' }],
name: [
{ required: true, message: '请输入科室名称', trigger: 'change' },
{ min: 2, max: 20, message: '长度在 2 到 20 个字符', trigger: 'change' },
],
typeEnum: [{ required: true, message: '请选择科室类型', trigger: 'change' }],
// 新增字段验证规则
location: [{ required: false, message: '请输入科室位置', trigger: 'blur' }],
intro: [{ required: false, message: '请输入科室简介', trigger: 'blur' }],
remark: [{ required: false, message: '请输入备注信息', trigger: 'blur' }],
});
getPageList();
initOption();
// 使用系统标准字典获取方法
const { organization_class } = proxy.useDict('organization_class');
// 统一的科室分类字典处理函数
function processOrganizationClassDict(dictData) {
return dictData.map(item => ({
value: String(item.value), // 将值转换为字符串类型,确保与表单值类型一致
info: item.label // 使用dict_label的值作为显示文本
}));
}
// 监听字典数据变化
watch(() => organization_class.value, (newVal) => {
if (newVal && newVal.length > 0) {
// 转换为组件需要的格式
classEnumOption.value = processOrganizationClassDict(newVal);
// 同步更新表格中显示的科室分类文本,确保主界面显示与字典一致
if (organization.value && organization.value.length > 0) {
organization.value = organization.value.map(item => {
// 保留原有显示文本作为基础
const originalText = item.classEnum_dictText || '';
// 获取字典中的对应文本
const dictLabel = getDictLabel(item.classEnum);
// 只有在字典中找到匹配值时才替换,否则保留原有文本
return {
...item,
classEnum_dictText: dictLabel || originalText
};
});
}
}
}, { immediate: true });
function initOption() {
if (orgTypeOption.value.length == 0) {
initOrgTypeOption().then((res) => {
orgTypeOption.value = res.data.organizationTypeOptions;
// 优先使用系统标准字典数据,确保编辑和新增科室使用相同的分类字典
if (organization_class.value && organization_class.value.length > 0) {
classEnumOption.value = processOrganizationClassDict(organization_class.value);
} else if (res.data.organizationClassOptions && res.data.organizationClassOptions.length > 0) {
// 只有在字典数据不存在时才使用接口返回的数据作为备选
// 将接口返回的科室分类选项值也转换为字符串类型,保持一致性
classEnumOption.value = res.data.organizationClassOptions.map(item => ({
...item,
value: String(item.value)
}));
}
});
}
}
function reset() {
form.value.id = undefined;
form.value.registerFlag = false;
form.value.location = undefined;
form.value.intro = undefined;
form.value.remark = undefined;
orgRef.value.resetFields();
}
// 从字典数据中查找对应的值,处理类型转换
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;
getPageList();
}
/** 重置按钮操作 */
function resetQuery() {
queryParams.value.name = undefined;
queryParams.value.typeEnum = undefined;
queryParams.value.classEnum = undefined;
queryParams.value.pageNo = 1;
getPageList();
}
function getPageList() {
loading.value = true;
getList(queryParams.value).then((res) => {
// 处理返回的科室数据,确保科室分类显示与系统标准字典一致
const processedData = res.data.records.map(item => {
// 保留原有显示文本作为基础
const originalText = item.classEnum_dictText || '';
// 如果系统标准字典存在,尝试使用字典中的文本覆盖原有文本
if (organization_class.value && organization_class.value.length > 0) {
// 处理多选值的情况
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: newText || originalText
};
}
return item;
});
organization.value = processedData;
total.value = res.data.total;
}).catch(error => {
console.error('获取科室列表失败:', error);
proxy.$modal.msgError('获取科室列表失败,请稍后重试');
organization.value = [];
total.value = 0;
}).finally(() => {
loading.value = false;
});
}
function handleAdd() {
title.value = '添加科室';
open.value = true;
reset();
console.log(form.value);
}
function handelEdit(row) {
console.log(row.busNo);
title.value = '编辑科室';
open.value = true;
// 调用后端API获取完整的科室信息确保包含所有字段
getOrgDetail(row.id).then(res => {
if (res.code === 200) {
const orgInfo = res.data;
form.value.id = orgInfo.id;
form.value.busNo = orgInfo.busNo;
form.value.name = orgInfo.name;
form.value.ybNo = orgInfo.ybNo;
form.value.ybName = orgInfo.ybName;
form.value.typeEnum = orgInfo.typeEnum;
// 处理多选的科室分类,如果是逗号分隔的字符串则转换为数组
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;
form.value.intro = orgInfo.intro;
form.value.remark = orgInfo.remark;
}
}).catch(error => {
console.error('获取科室信息失败:', error);
proxy.$modal.msgError('获取科室信息失败');
});
}
function cancel() {
open.value = false;
reset();
console.log(form.value);
}
// 新增/编辑
function submitForm() {
proxy.$refs['orgRef'].validate((valid) => {
if (valid) {
// 创建表单数据副本避免直接修改原始form对象
const formData = { ...form.value };
// 确保registerFlag从布尔值转换为整数true=1, false=0
formData.registerFlag = Number(formData.registerFlag ? 1 : 0);
// 处理多选的科室分类,如果是数组则转换为逗号分隔的字符串
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 = null;
}
// 验证提交数据
console.log('提交的数据:', formData);
if (form.value.id == undefined) {
if (form.value.busNoParent) {
formData.busNo = form.value.busNoParent;
}
addOrganization(formData).then((res) => {
proxy.$modal.msgSuccess('操作成功');
open.value = false;
getPageList();
}).catch(error => {
console.error('添加科室失败:', error);
proxy.$modal.msgError('添加科室失败,请稍后重试');
});
} else {
updateOrganization(formData).then((res) => {
proxy.$modal.msgSuccess('操作成功');
open.value = false;
getPageList();
}).catch(error => {
console.error('更新科室失败:', error);
proxy.$modal.msgError('更新科室失败,请稍后重试');
});
}
}
});
}
// 添加下级
function handleAddInferior(row) {
title.value = '添加下级';
open.value = true;
form.value.busNoParent = row.busNo;
}
// 删除
function handleDelete() {
loading.value = true;
deleteOrganization(selectRowIds.value.join(',')).then((res) => {
proxy.$modal.msgSuccess('操作成功');
getPageList();
}).catch(error => {
console.error('删除科室失败:', error);
proxy.$modal.msgError('删除科室失败,请稍后重试');
}).finally(() => {
loading.value = false;
});
}
// 停用
function handleDisabled(id) {
disableOrg(id).then((res) => {
proxy.$modal.msgSuccess('操作成功');
getPageList();
}).catch(error => {
console.error('停用科室失败:', error);
proxy.$modal.msgError('停用科室失败,请稍后重试');
});
}
// 启用
function handelEnable(id) {
enableOrg(id).then((res) => {
proxy.$modal.msgSuccess('操作成功');
getPageList();
}).catch(error => {
console.error('启用科室失败:', error);
proxy.$modal.msgError('启用科室失败,请稍后重试');
});
}
function handleSelectionChange() {
selectRowIds.value = orgTableRef.value.getSelectionRows().map((item) => item.id);
}
</script>