541
openhis-ui-vue3/src/views/basicmanage/implementDepartment/index.vue
Executable file
541
openhis-ui-vue3/src/views/basicmanage/implementDepartment/index.vue
Executable file
@@ -0,0 +1,541 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-row :gutter="20">
|
||||
<!--诊疗目录-->
|
||||
<el-col :span="4" :xs="24">
|
||||
<div class="head-title">执行科室配置</div>
|
||||
<div class="head-container">
|
||||
<el-tree
|
||||
:data="organization"
|
||||
:props="{ label: 'name', children: 'children' }"
|
||||
:expand-on-click-node="true"
|
||||
:filter-node-method="filterNode"
|
||||
ref="treeRef"
|
||||
node-key="id"
|
||||
highlight-current
|
||||
check-strictly
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
/>
|
||||
</div>
|
||||
</el-col>
|
||||
<!--诊疗目录-->
|
||||
<el-col :span="20" :xs="24">
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Plus"
|
||||
:disabled="isAddDisable"
|
||||
@click="handleAddItem"
|
||||
v-hasPermi="['system:user:add']"
|
||||
>添加新项目</el-button
|
||||
>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Plus"
|
||||
:disabled="isAddDisable"
|
||||
@click="handleBacthAddItem"
|
||||
v-hasPermi="['system:user:add']"
|
||||
>批量新增项目配置</el-button
|
||||
>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="catagoryList"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="100" align="center" />
|
||||
<el-table-column
|
||||
label="诊疗目录"
|
||||
width="150"
|
||||
align="center"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.activityCategoryCode"
|
||||
placeholder="请选择"
|
||||
ref="dropdown"
|
||||
:class="{ 'error-border': scope.row.error }"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in catagoryDicts"
|
||||
:key="dict.value"
|
||||
:label="dict.info"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="项目名称" align="center" :show-overflow-tooltip="true">
|
||||
<template #default="scope">
|
||||
<el-select
|
||||
v-model="scope.row.activityDefinitionId"
|
||||
filterable
|
||||
remote
|
||||
:remote-method="(query) => handleRemoteQuery(query, scope.row)"
|
||||
:loading="scope.row.loading"
|
||||
placeholder="请输入并搜索项目"
|
||||
style="width: 400px; max-width: 500px"
|
||||
:class="{ 'error-border': scope.row.error }"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item in scope.row.filteredOptions || []"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="开始时间"
|
||||
align="center"
|
||||
key="startTime"
|
||||
prop="startTime"
|
||||
:show-overflow-tooltip="true"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-time-picker
|
||||
v-model="scope.row.startTime"
|
||||
placeholder="选择时间"
|
||||
format="HH:mm:ss"
|
||||
value-format="HH:mm:ss"
|
||||
>
|
||||
</el-time-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="结束时间"
|
||||
align="center"
|
||||
key="endTime"
|
||||
prop="endTime"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-time-picker
|
||||
v-model="scope.row.endTime"
|
||||
placeholder="选择时间"
|
||||
format="HH:mm:ss"
|
||||
value-format="HH:mm:ss"
|
||||
>
|
||||
</el-time-picker>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
align="center"
|
||||
width="150"
|
||||
class-name="small-padding fixed-width"
|
||||
fixed="right"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
icon="Edit"
|
||||
@click="openSaveImplementDepartment(scope.row, scope.$index)"
|
||||
v-hasPermi="['system:user:edit']"
|
||||
>保存</el-button
|
||||
>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
icon="Delete"
|
||||
:disabled="scope.row.id == ''"
|
||||
@click="deleteSelectedRows(scope.row)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<BacthAddItemDialog
|
||||
v-model:dialogVisible="bacthAddItemDialogVisible"
|
||||
:organizationId="organizationId"
|
||||
@submitOk="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="implementDepartment">
|
||||
import {ref} from 'vue';
|
||||
import {
|
||||
addImplementDepartment,
|
||||
deleteImplementDepartment,
|
||||
editImplementDepartment,
|
||||
getAllTreatmentList,
|
||||
getDiagnosisTreatmentList,
|
||||
getDiseaseTreatmentInit,
|
||||
getImplementDepartmentList,
|
||||
} from './components/implementDepartment';
|
||||
import BacthAddItemDialog from './components/batchAddDialog.vue';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const organization = ref([]);
|
||||
const loading = ref(true);
|
||||
const ids = ref([]); // 存储选择的行数据
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const catagoryList = ref([]);
|
||||
const catagoryDicts = ref([]);
|
||||
const isAddDisable = ref(true);
|
||||
const organizationId = ref('');
|
||||
// 批量添加
|
||||
const bacthAddItemDialogVisible = ref(false);
|
||||
//默认传8(诊疗)
|
||||
const distributionCategoryCode = ref('8');
|
||||
const data = reactive({
|
||||
form: {},
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
tableRules: {
|
||||
activityCategoryCode: [{ required: true, message: '诊疗目录不能为空', trigger: 'blur' }],
|
||||
activityDefinitionId: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }],
|
||||
},
|
||||
isAdding: false,
|
||||
});
|
||||
const { queryParams, tableRules } = toRefs(data);
|
||||
/** 查询表格数据列表 */
|
||||
function getList() {
|
||||
queryParams.value.organizationId = organizationId.value;
|
||||
queryParams.value.distributionCategoryCode = distributionCategoryCode.value;
|
||||
loading.value = true;
|
||||
getDiagnosisTreatmentList(queryParams.value).then((res) => {
|
||||
loading.value = false;
|
||||
catagoryList.value = res.data.records.map(record => {
|
||||
const filteredOptions = allImplementDepartmentList.value.slice(0, 100);
|
||||
// 确保后端返回的项目名称选项存在于 filteredOptions 中,避免 el-select 因找不到选项而回显为 ID
|
||||
if (record.activityDefinitionId && !filteredOptions.some(o => o.value === record.activityDefinitionId)) {
|
||||
filteredOptions.push({
|
||||
value: record.activityDefinitionId,
|
||||
label: record.activityDefinitionId_dictText || record.activityDefinitionId
|
||||
});
|
||||
}
|
||||
return {
|
||||
...record,
|
||||
loading: false,
|
||||
filteredOptions: filteredOptions
|
||||
};
|
||||
});
|
||||
total.value = res.data.total;
|
||||
});
|
||||
}
|
||||
/** 通过条件过滤节点 */
|
||||
const filterNode = (value, data) => {
|
||||
if (!value) return true;
|
||||
return data.name.indexOf(value) !== -1;
|
||||
};
|
||||
// 所有诊疗项目列表
|
||||
const allImplementDepartmentList = ref([]);
|
||||
async function getAllImplementDepartment() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res = await getAllTreatmentList();
|
||||
allImplementDepartmentList.value = res.data.map((item) => ({
|
||||
value: item.activityDefinitionId,
|
||||
label: item.activityDefinitionName,
|
||||
}));
|
||||
|
||||
// 为所有现有行初始化过滤选项(使用防抖处理,避免频繁更新)
|
||||
if (catagoryList.value && catagoryList.value.length > 0) {
|
||||
// 使用 setTimeout 将 DOM 更新推迟到下一个事件循环,避免阻塞
|
||||
setTimeout(() => {
|
||||
catagoryList.value.forEach(row => {
|
||||
if (!row.hasOwnProperty('filteredOptions')) {
|
||||
row.filteredOptions = allImplementDepartmentList.value.slice(0, 100); // 限制为前100个
|
||||
row.loading = false;
|
||||
}
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
loading.value = false;
|
||||
} catch (error) {
|
||||
console.error('获取诊疗项目列表失败:', error);
|
||||
loading.value = false;
|
||||
proxy.$message.error('获取诊疗项目列表失败');
|
||||
}
|
||||
}
|
||||
|
||||
/** 选择条数 */
|
||||
function handleSelectionChange(selection) {
|
||||
ids.value = selection.map((item) => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
}
|
||||
// 远程搜索处理函数
|
||||
function handleRemoteQuery(query, row) {
|
||||
if (query !== '') {
|
||||
// 设置加载状态
|
||||
row.loading = true;
|
||||
// 模拟异步延迟
|
||||
setTimeout(() => {
|
||||
// 确保数据已加载
|
||||
if (!allImplementDepartmentList.value || allImplementDepartmentList.value.length === 0) {
|
||||
row.filteredOptions = [];
|
||||
row.loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// 过滤选项,限制结果数量以提高性能
|
||||
const filtered = allImplementDepartmentList.value.filter(item => {
|
||||
return item.label.toLowerCase().includes(query.toLowerCase()) ||
|
||||
item.value.toLowerCase().includes(query.toLowerCase());
|
||||
});
|
||||
|
||||
// 限制返回结果数量,避免过多选项导致性能问题
|
||||
row.filteredOptions = filtered.slice(0, 100); // 限制为前100个匹配项
|
||||
row.loading = false;
|
||||
}, 300); // 300ms 延迟,模拟网络请求
|
||||
} else {
|
||||
// 如果查询为空,显示所有选项(但限制数量以提高性能)
|
||||
if (allImplementDepartmentList.value && allImplementDepartmentList.value.length > 0) {
|
||||
row.filteredOptions = allImplementDepartmentList.value.slice(0, 100); // 限制为前100个
|
||||
} else {
|
||||
row.filteredOptions = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 新增项目
|
||||
function handleAddItem() {
|
||||
if (data.isAdding) {
|
||||
proxy.$message.warning('请先保存当前行后再新增!');
|
||||
return;
|
||||
}
|
||||
|
||||
// 确保 allImplementDepartmentList 已经初始化
|
||||
if (!allImplementDepartmentList.value || allImplementDepartmentList.value.length === 0) {
|
||||
proxy.$message.warning('正在加载数据,请稍后再试!');
|
||||
// 如果数据还未加载完成,尝试重新加载
|
||||
getAllImplementDepartment();
|
||||
return;
|
||||
}
|
||||
|
||||
const newRow = {
|
||||
startTime: '00:00:00',
|
||||
endTime: '23:59:59',
|
||||
loading: false, // 添加加载状态
|
||||
filteredOptions: allImplementDepartmentList.value.slice(0, 100), // 初始化过滤选项,限制数量
|
||||
};
|
||||
catagoryList.value.push(newRow);
|
||||
total.value = catagoryList.value.length; // 修正:使用实际数据列表长度,而不是组织结构长度
|
||||
data.isAdding = true; // 设置标志位为 true,表示有未保存的
|
||||
}
|
||||
// 批量添加
|
||||
function handleBacthAddItem() {
|
||||
// 批量添加显示对话框
|
||||
bacthAddItemDialogVisible.value = true;
|
||||
}
|
||||
|
||||
// 检验 编辑或 保存数据
|
||||
function handleBlur(row, index) {
|
||||
let hasError = false;
|
||||
const fields = ['activityCategoryCode', 'activityDefinitionId', 'startTime', 'endTime'];
|
||||
|
||||
fields.forEach((field) => {
|
||||
if (!row[field]) {
|
||||
hasError = true;
|
||||
const message = tableRules.value[field]?.[0]?.message;
|
||||
if (message) {
|
||||
proxy.$message.error(message);
|
||||
} else {
|
||||
proxy.$message.error(`检验未通过`);
|
||||
}
|
||||
}
|
||||
});
|
||||
row.error = hasError;
|
||||
}
|
||||
|
||||
// 编辑或 保存当前行
|
||||
function openSaveImplementDepartment(row) {
|
||||
const params = {
|
||||
// 科室id
|
||||
organizationId: organizationId.value,
|
||||
// 类别
|
||||
distributionCategoryCode: distributionCategoryCode.value,
|
||||
...row,
|
||||
};
|
||||
let hasError = false;
|
||||
handleBlur(row);
|
||||
if (row.error) {
|
||||
hasError = true;
|
||||
return;
|
||||
}
|
||||
const startTime = params.startTime;
|
||||
const endTime = params.endTime;
|
||||
if (startTime > endTime) {
|
||||
proxy.$message.error('开始时间不能大于结束时间');
|
||||
return;
|
||||
}
|
||||
if (hasError) {
|
||||
proxy.$message.error('请填写完整信息');
|
||||
return;
|
||||
}
|
||||
if (row.id) {
|
||||
editImplementDepartment(params).then((res) => {
|
||||
data.isAdding = false; // 允许新增下一行
|
||||
proxy.$modal.msgSuccess('保存成功!');
|
||||
// 确保选中项在 filteredOptions 中,使 el-select 能正确显示名称
|
||||
const savedItem = allImplementDepartmentList.value.find(i => i.value === row.activityDefinitionId);
|
||||
if (savedItem && !row.filteredOptions.some(o => o.value === row.activityDefinitionId)) {
|
||||
row.filteredOptions.push(savedItem);
|
||||
}
|
||||
getList();
|
||||
});
|
||||
} else {
|
||||
delete params.id;
|
||||
addImplementDepartment(params).then((res) => {
|
||||
data.isAdding = false; // 允许新增下一行
|
||||
proxy.$modal.msgSuccess('保存成功!');
|
||||
// 确保选中项在 filteredOptions 中,使 el-select 能正确显示名称
|
||||
const savedItem = allImplementDepartmentList.value.find(i => i.value === row.activityDefinitionId);
|
||||
if (savedItem && !row.filteredOptions.some(o => o.value === row.activityDefinitionId)) {
|
||||
row.filteredOptions.push(savedItem);
|
||||
}
|
||||
getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
// 删除当前所选行
|
||||
function deleteSelectedRows(row) {
|
||||
proxy.$modal.confirm('是否删除选中数据').then(() => {
|
||||
if (row.id) {
|
||||
deleteImplementDepartment({ orgLocId: row.id }).then((res) => {
|
||||
if (res.code === 200) {
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
}
|
||||
}).catch(() => {
|
||||
proxy.$modal.msgError('删除失败');
|
||||
});
|
||||
} else {
|
||||
catagoryList.value.pop();
|
||||
proxy.$modal.msgSuccess('删除成功');
|
||||
}
|
||||
data.isAdding = false;
|
||||
getList();
|
||||
});
|
||||
}
|
||||
/** 节点单击事件 */
|
||||
function handleNodeClick(res, node) {
|
||||
// 检查是否有未保存的数据
|
||||
if (data.isAdding) {
|
||||
proxy.$modal.confirm('当前有未保存的数据,切换节点将丢失未保存的数据,是否继续?').then(() => {
|
||||
// 确认切换,重置状态
|
||||
data.isAdding = false;
|
||||
continueHandleNodeClick(node);
|
||||
}).catch(() => {
|
||||
// 取消切换,保持当前状态
|
||||
return;
|
||||
});
|
||||
} else {
|
||||
continueHandleNodeClick(node);
|
||||
}
|
||||
}
|
||||
|
||||
// 实际的节点点击处理逻辑
|
||||
function continueHandleNodeClick(node) {
|
||||
// 新增按钮是否 disable
|
||||
isAddDisable.value = false;
|
||||
// 检查节点是否有子节点
|
||||
if (node.data.children && node.data.children.length > 0) {
|
||||
// proxy.$message.warning("不能选择父节点");
|
||||
return;
|
||||
}
|
||||
// 选中科室id
|
||||
organizationId.value = node.data.id;
|
||||
// 获取 右侧 table 信息
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 目录分类查询 */
|
||||
async function getDiseaseTreatmentList() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const { data } = await getDiseaseTreatmentInit();
|
||||
|
||||
// 分类目录初始化获取
|
||||
catagoryDicts.value = data.diagnosisCategoryOptions.sort((a, b) => {
|
||||
return parseInt(a.value) - parseInt(b.value);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('获取疾病治疗初始化数据失败:', error);
|
||||
proxy.$message.error('获取分类目录失败');
|
||||
}
|
||||
|
||||
// 诊疗目录分类查询下拉树结构
|
||||
await getImplDepartList();
|
||||
loading.value = false;
|
||||
}
|
||||
// 诊疗目录分类查询下拉树结d构
|
||||
async function getImplDepartList() {
|
||||
try {
|
||||
// 只查询科室类型(typeEnum=2),不包含专业等其他类型
|
||||
const res = await getImplementDepartmentList({ typeEnum: 2 });
|
||||
if (res.code === 200) {
|
||||
if (res.data.records.length > 0) {
|
||||
organization.value = res.data.records.map((res) => {
|
||||
return {
|
||||
...res,
|
||||
isEditing: false, // 标记当前行是否正在编辑
|
||||
error: false, // 新增 error 字段
|
||||
};
|
||||
});
|
||||
} else {
|
||||
organization.value = [];
|
||||
}
|
||||
} else {
|
||||
proxy.$modal.msgError(res.code);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取实施部门列表失败:', error);
|
||||
proxy.$message.error('获取科室信息失败');
|
||||
}
|
||||
}
|
||||
onMounted(async () => {
|
||||
try {
|
||||
// 并行加载数据,提高效率
|
||||
await Promise.all([
|
||||
getAllImplementDepartment(),
|
||||
getDiseaseTreatmentList()
|
||||
]);
|
||||
} catch (error) {
|
||||
console.error('初始化数据加载失败:', error);
|
||||
proxy.$message.error('数据加载失败,请稍后重试');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-form--inline .el-form-item {
|
||||
display: inline-flex;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
||||
.error-border {
|
||||
border: 1px solid red;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user