367 lines
9.9 KiB
Vue
367 lines
9.9 KiB
Vue
<template>
|
||
<div class="hospitals-container">
|
||
<el-card>
|
||
<!-- Header / Actions -->
|
||
<div class="header-actions">
|
||
<el-form :inline="true" :model="searchForm" class="search-form">
|
||
<el-form-item label="医院名称">
|
||
<el-input
|
||
v-model="searchForm.keyword"
|
||
placeholder="请输入关键词"
|
||
clearable
|
||
/>
|
||
</el-form-item>
|
||
<el-form-item>
|
||
<el-button type="primary" @click="fetchData" icon="Search"
|
||
>查询</el-button
|
||
>
|
||
<el-button @click="resetSearch" icon="Refresh">重置</el-button>
|
||
<el-button
|
||
v-if="userStore.role === 'SYSTEM_ADMIN'"
|
||
type="success"
|
||
@click="openCreateDialog"
|
||
icon="Plus"
|
||
>新增医院</el-button
|
||
>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
|
||
<!-- Table -->
|
||
<el-table
|
||
:data="tableData"
|
||
v-loading="loading"
|
||
border
|
||
stripe
|
||
style="width: 100%"
|
||
>
|
||
<el-table-column prop="id" label="ID" width="80" align="center" />
|
||
<el-table-column prop="name" label="医院名称" min-width="200" />
|
||
<el-table-column prop="adminDisplay" label="医院管理员" min-width="220">
|
||
<template #default="{ row }">
|
||
{{ row.adminDisplay || '未设置' }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="createdAt" label="创建时间" width="180">
|
||
<template #default="{ row }">
|
||
{{ new Date(row.createdAt).toLocaleString() }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" width="250" fixed="right" align="center">
|
||
<template #default="{ row }">
|
||
<el-button size="small" @click="goToDepartments(row)"
|
||
>管理科室</el-button
|
||
>
|
||
<el-button size="small" type="primary" @click="openEditDialog(row)"
|
||
>编辑</el-button
|
||
>
|
||
<el-button
|
||
v-if="userStore.role === 'SYSTEM_ADMIN'"
|
||
size="small"
|
||
type="danger"
|
||
@click="handleDelete(row)"
|
||
>删除</el-button
|
||
>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<!-- Pagination -->
|
||
<div class="pagination-container">
|
||
<el-pagination
|
||
v-model:current-page="page"
|
||
v-model:page-size="pageSize"
|
||
:page-sizes="[10, 20, 50, 100]"
|
||
:total="total"
|
||
background
|
||
layout="total, sizes, prev, pager, next, jumper"
|
||
@size-change="fetchData"
|
||
@current-change="fetchData"
|
||
/>
|
||
</div>
|
||
</el-card>
|
||
|
||
<!-- Dialog for Create / Edit -->
|
||
<el-dialog
|
||
:title="isEdit ? '编辑医院' : '新增医院'"
|
||
v-model="dialogVisible"
|
||
width="500px"
|
||
@close="resetForm"
|
||
>
|
||
<el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
|
||
<el-form-item label="医院名称" prop="name">
|
||
<el-input v-model="form.name" placeholder="请输入医院名称" />
|
||
</el-form-item>
|
||
<el-form-item
|
||
label="医院管理员"
|
||
v-if="userStore.role === 'SYSTEM_ADMIN'"
|
||
>
|
||
<el-select
|
||
v-model="form.adminUserId"
|
||
placeholder="可选:选择后将任命为医院管理员"
|
||
clearable
|
||
filterable
|
||
style="width: 100%"
|
||
>
|
||
<el-option
|
||
v-for="user in hospitalAdminOptions"
|
||
:key="user.id"
|
||
:label="`${user.name}(${user.phone} / ${getRoleName(user.role)})`"
|
||
:value="user.id"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
</el-form>
|
||
<template #footer>
|
||
<div class="dialog-footer">
|
||
<el-button @click="dialogVisible = false">取消</el-button>
|
||
<el-button
|
||
type="primary"
|
||
@click="handleSubmit"
|
||
:loading="submitLoading"
|
||
>确定</el-button
|
||
>
|
||
</div>
|
||
</template>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, onMounted } from 'vue';
|
||
import { useRouter } from 'vue-router';
|
||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||
import {
|
||
getHospitals,
|
||
createHospital,
|
||
updateHospital,
|
||
deleteHospital,
|
||
} from '../../api/organization';
|
||
import { getUsers, updateUser } from '../../api/users';
|
||
import { useUserStore } from '../../store/user';
|
||
|
||
const router = useRouter();
|
||
const userStore = useUserStore();
|
||
|
||
// --- State ---
|
||
const loading = ref(false);
|
||
const tableData = ref([]);
|
||
const total = ref(0);
|
||
const page = ref(1);
|
||
const pageSize = ref(10);
|
||
const hospitalAdminOptions = ref([]);
|
||
|
||
const roleMap = {
|
||
SYSTEM_ADMIN: '系统管理员',
|
||
HOSPITAL_ADMIN: '医院管理员',
|
||
DIRECTOR: '科室主任',
|
||
LEADER: '小组组长',
|
||
DOCTOR: '医生',
|
||
ENGINEER: '工程师',
|
||
};
|
||
|
||
const getRoleName = (role) => roleMap[role] || role;
|
||
|
||
const searchForm = reactive({
|
||
keyword: '',
|
||
});
|
||
|
||
// Dialog State
|
||
const dialogVisible = ref(false);
|
||
const isEdit = ref(false);
|
||
const submitLoading = ref(false);
|
||
const formRef = ref(null);
|
||
const currentId = ref(null);
|
||
|
||
const form = reactive({
|
||
name: '',
|
||
adminUserId: null,
|
||
});
|
||
|
||
const rules = {
|
||
name: [{ required: true, message: '请输入医院名称', trigger: 'blur' }],
|
||
};
|
||
|
||
// --- Methods ---
|
||
const fetchData = async () => {
|
||
loading.value = true;
|
||
try {
|
||
const res = await getHospitals({
|
||
page: page.value,
|
||
pageSize: pageSize.value,
|
||
keyword: searchForm.keyword || undefined,
|
||
});
|
||
|
||
let hospitalAdminNameMap = {};
|
||
try {
|
||
const userRes = await getUsers();
|
||
const users = Array.isArray(userRes?.list) ? userRes.list : [];
|
||
hospitalAdminNameMap = users.reduce((acc, user) => {
|
||
if (user.role !== 'HOSPITAL_ADMIN' || !user.hospitalId) {
|
||
return acc;
|
||
}
|
||
if (!acc[user.hospitalId]) {
|
||
acc[user.hospitalId] = [];
|
||
}
|
||
acc[user.hospitalId].push(user.name || '-');
|
||
return acc;
|
||
}, {});
|
||
} catch (error) {
|
||
console.error('Failed to fetch hospital admins', error);
|
||
}
|
||
|
||
tableData.value = (res.list || []).map((hospital) => ({
|
||
...hospital,
|
||
adminDisplay:
|
||
(hospitalAdminNameMap[hospital.id] || []).join('、') || '未设置',
|
||
}));
|
||
total.value = res.total || 0;
|
||
} catch (error) {
|
||
console.error('Failed to fetch hospitals', error);
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
};
|
||
|
||
const resetSearch = () => {
|
||
searchForm.keyword = '';
|
||
page.value = 1;
|
||
fetchData();
|
||
};
|
||
|
||
const openCreateDialog = () => {
|
||
isEdit.value = false;
|
||
currentId.value = null;
|
||
loadHospitalAdminOptions();
|
||
dialogVisible.value = true;
|
||
};
|
||
|
||
const openEditDialog = (row) => {
|
||
isEdit.value = true;
|
||
currentId.value = row.id;
|
||
form.name = row.name;
|
||
loadHospitalAdminOptions(row.id);
|
||
dialogVisible.value = true;
|
||
};
|
||
|
||
const resetForm = () => {
|
||
if (formRef.value) {
|
||
formRef.value.resetFields();
|
||
}
|
||
form.name = '';
|
||
form.adminUserId = null;
|
||
};
|
||
|
||
const loadHospitalAdminOptions = async (hospitalId) => {
|
||
if (userStore.role !== 'SYSTEM_ADMIN') {
|
||
hospitalAdminOptions.value = [];
|
||
return;
|
||
}
|
||
|
||
const userRes = await getUsers();
|
||
const users = Array.isArray(userRes?.list) ? userRes.list : [];
|
||
hospitalAdminOptions.value = users.filter((user) => {
|
||
// 仅允许选择“医院管理员”角色,避免误选普通人员。
|
||
if (user.role !== 'HOSPITAL_ADMIN') {
|
||
return false;
|
||
}
|
||
if (!hospitalId) {
|
||
return true;
|
||
}
|
||
return user.hospitalId == null || user.hospitalId === hospitalId;
|
||
});
|
||
};
|
||
|
||
const handleSubmit = async () => {
|
||
if (!formRef.value) return;
|
||
await formRef.value.validate(async (valid) => {
|
||
if (valid) {
|
||
submitLoading.value = true;
|
||
try {
|
||
let targetHospitalId = null;
|
||
if (isEdit.value) {
|
||
const updated = await updateHospital(currentId.value, {
|
||
name: form.name,
|
||
});
|
||
targetHospitalId = updated?.id ?? currentId.value;
|
||
ElMessage.success('更新成功');
|
||
} else {
|
||
const created = await createHospital({ name: form.name });
|
||
targetHospitalId = created?.id;
|
||
ElMessage.success('创建成功');
|
||
}
|
||
|
||
if (form.adminUserId && targetHospitalId) {
|
||
const selectedAdmin = hospitalAdminOptions.value.find(
|
||
(user) => user.id === form.adminUserId,
|
||
);
|
||
if (!selectedAdmin || selectedAdmin.role !== 'HOSPITAL_ADMIN') {
|
||
ElMessage.error('仅可选择医院管理员角色人员');
|
||
return;
|
||
}
|
||
|
||
await updateUser(form.adminUserId, {
|
||
role: 'HOSPITAL_ADMIN',
|
||
hospitalId: targetHospitalId,
|
||
departmentId: null,
|
||
groupId: null,
|
||
});
|
||
ElMessage.success('医院管理员已设置');
|
||
}
|
||
|
||
dialogVisible.value = false;
|
||
fetchData();
|
||
} catch (error) {
|
||
console.error('Submit failed', error);
|
||
} finally {
|
||
submitLoading.value = false;
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
const handleDelete = (row) => {
|
||
ElMessageBox.confirm(`确定要删除医院 "${row.name}" 吗?`, '警告', {
|
||
confirmButtonText: '确定',
|
||
cancelButtonText: '取消',
|
||
type: 'warning',
|
||
})
|
||
.then(async () => {
|
||
try {
|
||
await deleteHospital(row.id);
|
||
ElMessage.success('删除成功');
|
||
fetchData();
|
||
} catch (error) {
|
||
console.error('Delete failed', error);
|
||
}
|
||
})
|
||
.catch(() => {});
|
||
};
|
||
|
||
const goToDepartments = (row) => {
|
||
router.push({
|
||
path: '/organization/departments',
|
||
query: { hospitalId: row.id, hospitalName: row.name },
|
||
});
|
||
};
|
||
|
||
// --- Lifecycle ---
|
||
onMounted(() => {
|
||
fetchData();
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
.hospitals-container {
|
||
padding: 0;
|
||
}
|
||
.header-actions {
|
||
margin-bottom: 20px;
|
||
}
|
||
.pagination-container {
|
||
margin-top: 20px;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
}
|
||
</style>
|