- 移除住院参与者更新失败时的异常返回,改为静默处理 - 更新床位分配提示信息,为用户提供更清晰的操作指导 - 实现实施科室下拉选择器的远程搜索功能,提升大数据量下的用户体验 - 添加节点切换时的未保存数据确认提醒,防止数据丢失 - 优化实施科室管理页面的选项过滤和加载状态管理
466 lines
14 KiB
Vue
466 lines
14 KiB
Vue
<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;
|
||
total.value = res.data.total;
|
||
});
|
||
}
|
||
/** 通过条件过滤节点 */
|
||
const filterNode = (value, data) => {
|
||
if (!value) return true;
|
||
return data.name.indexOf(value) !== -1;
|
||
};
|
||
// 所有诊疗项目列表
|
||
const allImplementDepartmentList = ref([]);
|
||
function getAllImplementDepartment() {
|
||
loading.value = true;
|
||
getAllTreatmentList().then((res) => {
|
||
allImplementDepartmentList.value = res.data.map((item) => ({
|
||
value: item.activityDefinitionId,
|
||
label: item.activityDefinitionName,
|
||
}));
|
||
|
||
// 为所有现有行初始化过滤选项
|
||
catagoryList.value.forEach(row => {
|
||
if (!row.hasOwnProperty('filteredOptions')) {
|
||
row.filteredOptions = allImplementDepartmentList.value.slice(0, 100); // 限制为前100个
|
||
row.loading = false;
|
||
}
|
||
});
|
||
|
||
loading.value = false;
|
||
});
|
||
}
|
||
|
||
/** 选择条数 */
|
||
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(() => {
|
||
// 过滤选项
|
||
row.filteredOptions = allImplementDepartmentList.value.filter(item => {
|
||
return item.label.toLowerCase().includes(query.toLowerCase()) ||
|
||
item.value.toLowerCase().includes(query.toLowerCase());
|
||
});
|
||
row.loading = false;
|
||
}, 300); // 300ms 延迟,模拟网络请求
|
||
} else {
|
||
// 如果查询为空,显示所有选项(但限制数量以提高性能)
|
||
row.filteredOptions = allImplementDepartmentList.value.slice(0, 100); // 限制为前100个
|
||
}
|
||
}
|
||
|
||
// 新增项目
|
||
function handleAddItem() {
|
||
if (data.isAdding) {
|
||
proxy.$message.warning('请先保存当前行后再新增!');
|
||
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('保存成功!');
|
||
});
|
||
} else {
|
||
delete params.id;
|
||
addImplementDepartment(params).then((res) => {
|
||
data.isAdding = false; // 允许新增下一行
|
||
proxy.$modal.msgSuccess('保存成功!');
|
||
});
|
||
}
|
||
}
|
||
// 删除当前所选行
|
||
function deleteSelectedRows(row) {
|
||
proxy.$modal.confirm('是否删除选中数据').then(() => {
|
||
if (row.id) {
|
||
deleteImplementDepartment({ orgLocId: row.id }).then((res) => {});
|
||
} 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
|
||
if (node.parent === null || node.level === 1) {
|
||
isAddDisable.value = true;
|
||
} else {
|
||
isAddDisable.value = false;
|
||
}
|
||
// 检查节点是否有子节点
|
||
if (node.data.children && node.data.children.length > 0) {
|
||
// proxy.$message.warning("不能选择父节点");
|
||
return;
|
||
}
|
||
// 选中科室id
|
||
organizationId.value = node.data.id;
|
||
// 获取 右侧 table 信息
|
||
getList();
|
||
}
|
||
|
||
/** 目录分类查询 */
|
||
function getDiseaseTreatmentList() {
|
||
loading.value = true;
|
||
getDiseaseTreatmentInit().then(({ data }) => {
|
||
loading.value = false;
|
||
|
||
//分类目录初始化获取
|
||
catagoryDicts.value = data.diagnosisCategoryOptions.sort((a, b) => {
|
||
return parseInt(a.value) - parseInt(b.value);
|
||
});
|
||
});
|
||
// 诊疗目录分类查询下拉树结d构
|
||
loading.value = true;
|
||
// 诊疗目录分类查询下拉树结d构
|
||
getImplDepartList();
|
||
}
|
||
// 诊疗目录分类查询下拉树结d构
|
||
function getImplDepartList() {
|
||
loading.value = true;
|
||
getImplementDepartmentList().then((res) => {
|
||
loading.value = false;
|
||
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 {
|
||
this.$modal.msgError(res.code);
|
||
}
|
||
});
|
||
}
|
||
onMounted(() => {
|
||
getAllImplementDepartment();
|
||
getDiseaseTreatmentList();
|
||
});
|
||
</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> |