@@ -129,6 +129,7 @@ const activeMenu = computed(() => {
return route.path;
});
+const isDirector = computed(() => userStore.role === 'DIRECTOR');
const canAccessUsers = computed(() =>
hasRolePermission(userStore.role, ROLE_PERMISSIONS.USERS),
);
@@ -138,12 +139,18 @@ const canAccessDevices = computed(() =>
const canAccessOrgTree = computed(() =>
hasRolePermission(userStore.role, ROLE_PERMISSIONS.ORG_TREE),
);
+const canAccessDepartments = computed(() =>
+ hasRolePermission(userStore.role, ROLE_PERMISSIONS.ORG_DEPARTMENTS),
+);
const canAccessTasks = computed(() =>
hasRolePermission(userStore.role, ROLE_PERMISSIONS.TASKS),
);
const canAccessPatients = computed(() =>
hasRolePermission(userStore.role, ROLE_PERMISSIONS.PATIENTS),
);
+const usersMenuLabel = computed(() =>
+ isDirector.value ? '医生管理' : '用户管理',
+);
const handleCommand = (command) => {
if (command === 'logout') {
diff --git a/tyt-admin/src/views/Dashboard.vue b/tyt-admin/src/views/Dashboard.vue
index c8eef01..117e6da 100644
--- a/tyt-admin/src/views/Dashboard.vue
+++ b/tyt-admin/src/views/Dashboard.vue
@@ -5,17 +5,13 @@
当前角色:{{ userStore.role || '未登录' }}
-
+
-
+
{{ item.title }}
{{ item.value }}
@@ -75,19 +77,44 @@ const isSystemAdmin = computed(() => userStore.role === 'SYSTEM_ADMIN');
const canViewOrg = computed(() =>
['SYSTEM_ADMIN', 'HOSPITAL_ADMIN'].includes(userStore.role),
);
+const canViewUsers = computed(() =>
+ ['SYSTEM_ADMIN', 'HOSPITAL_ADMIN', 'DIRECTOR'].includes(userStore.role),
+);
const canViewPatients = computed(() =>
['SYSTEM_ADMIN', 'HOSPITAL_ADMIN', 'DIRECTOR', 'LEADER', 'DOCTOR'].includes(
userStore.role,
),
);
-const statCards = computed(() => [
- { key: 'hospitals', title: '医院总数', value: stats.value.hospitals },
- { key: 'departments', title: '科室总数', value: stats.value.departments },
- { key: 'groups', title: '小组总数', value: stats.value.groups },
- { key: 'users', title: '用户总数', value: stats.value.users },
- { key: 'patients', title: '可见患者数', value: stats.value.patients },
-]);
+const statCards = computed(() => {
+ const cards = [];
+
+ if (canViewOrg.value) {
+ cards.push(
+ { key: 'hospitals', title: '医院总数', value: stats.value.hospitals },
+ { key: 'departments', title: '科室总数', value: stats.value.departments },
+ { key: 'groups', title: '小组总数', value: stats.value.groups },
+ );
+ }
+
+ if (canViewUsers.value) {
+ cards.push({
+ key: 'users',
+ title: userStore.role === 'DIRECTOR' ? '本科室医生数' : '用户总数',
+ value: stats.value.users,
+ });
+ }
+
+ if (canViewPatients.value) {
+ cards.push({
+ key: 'patients',
+ title: '可见患者数',
+ value: stats.value.patients,
+ });
+ }
+
+ return cards;
+});
const fetchHospitalsForFilter = async () => {
if (!isSystemAdmin.value) {
@@ -104,16 +131,23 @@ const fetchDashboardData = async () => {
loading.value = true;
try {
if (canViewOrg.value) {
- const [hospitalRes, departmentRes, groupRes, usersRes] = await Promise.all([
+ const [hospitalRes, departmentRes, groupRes] = await Promise.all([
getHospitals({ page: 1, pageSize: 1 }),
getDepartments({ page: 1, pageSize: 1 }),
getGroups({ page: 1, pageSize: 1 }),
- getUsers({ page: 1, pageSize: 1 }),
]);
stats.value.hospitals = hospitalRes.total ?? 0;
stats.value.departments = departmentRes.total ?? 0;
stats.value.groups = groupRes.total ?? 0;
+ }
+
+ if (canViewUsers.value) {
+ const usersRes = await getUsers({
+ page: 1,
+ pageSize: 1,
+ role: userStore.role === 'DIRECTOR' ? 'DOCTOR' : undefined,
+ });
stats.value.users = usersRes.total ?? 0;
}
@@ -126,7 +160,9 @@ const fetchDashboardData = async () => {
stats.value.patients = 0;
} else {
const patientRes = await getPatients(params);
- stats.value.patients = Array.isArray(patientRes) ? patientRes.length : 0;
+ stats.value.patients = Array.isArray(patientRes)
+ ? patientRes.length
+ : 0;
}
}
} finally {
diff --git a/tyt-admin/src/views/users/Users.vue b/tyt-admin/src/views/users/Users.vue
index 876bdb8..ee98bc1 100644
--- a/tyt-admin/src/views/users/Users.vue
+++ b/tyt-admin/src/views/users/Users.vue
@@ -10,18 +10,18 @@
clearable
/>
-
+
-
-
-
-
-
-
+
@@ -30,7 +30,7 @@
重置
- 新增用户
+ {{ createButtonText }}
@@ -84,7 +84,7 @@
编辑
+
-
-
-
-
-
-
+
@@ -150,6 +156,7 @@
v-model="form.hospitalId"
placeholder="请选择医院"
style="width: 100%"
+ :disabled="lockHospital"
>
userStore.role === 'DIRECTOR');
const searchForm = reactive({
keyword: '',
- role: '',
+ role: isDirector.value ? 'DOCTOR' : '',
});
const dialogVisible = ref(false);
@@ -306,11 +324,24 @@ const assignDialogVisible = ref(false);
const currentAssignUser = ref(null);
const assignHospitalId = ref(null);
+const createButtonText = computed(() =>
+ isDirector.value ? '新增医生' : '新增用户',
+);
+const dialogTitle = computed(() => {
+ if (isDirector.value) {
+ return isEdit.value ? '编辑医生' : '新增医生';
+ }
+ return isEdit.value ? '编辑用户' : '新增用户';
+});
const needHospital = computed(() => form.role && form.role !== 'SYSTEM_ADMIN');
const needDepartment = computed(() =>
['DIRECTOR', 'LEADER', 'DOCTOR'].includes(form.role),
);
const needGroup = computed(() => ['LEADER', 'DOCTOR'].includes(form.role));
+const lockHospital = computed(() =>
+ ['HOSPITAL_ADMIN', 'DIRECTOR'].includes(userStore.role),
+);
+const lockDepartment = computed(() => isDirector.value);
const rules = computed(() => ({
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
@@ -379,6 +410,16 @@ const resolveGroupName = (id) => {
return groupMap.value.get(id) || `#${id}`;
};
+const resolveDirectorScope = () => {
+ const hospitalId = userStore.userInfo?.hospitalId || null;
+ const departmentId = userStore.userInfo?.departmentId || null;
+ if (!hospitalId || !departmentId) {
+ ElMessage.error('当前主任账号缺少医院或科室归属');
+ return null;
+ }
+ return { hospitalId, departmentId };
+};
+
const fetchCommonData = async () => {
const [hospitalRes, departmentRes, groupRes] = await Promise.all([
getHospitals({ page: 1, pageSize: 100 }),
@@ -427,7 +468,7 @@ const fetchData = async () => {
const res = await getUsers({
page: page.value,
pageSize: pageSize.value,
- role: searchForm.role || undefined,
+ role: (isDirector.value ? 'DOCTOR' : searchForm.role) || undefined,
keyword: searchForm.keyword || undefined,
});
tableData.value = res.list || [];
@@ -444,15 +485,29 @@ const handleSearch = () => {
const resetSearch = () => {
searchForm.keyword = '';
- searchForm.role = '';
+ searchForm.role = isDirector.value ? 'DOCTOR' : '';
page.value = 1;
fetchData();
};
const openCreateDialog = async () => {
+ resetForm();
isEdit.value = false;
currentId.value = null;
- dialogVisible.value = true;
+
+ if (isDirector.value) {
+ const directorScope = resolveDirectorScope();
+ if (!directorScope) {
+ return;
+ }
+ form.role = 'DOCTOR';
+ form.hospitalId = directorScope.hospitalId;
+ await fetchDepartmentsForForm(form.hospitalId);
+ form.departmentId = directorScope.departmentId;
+ await fetchGroupsForForm(form.departmentId);
+ dialogVisible.value = true;
+ return;
+ }
if (userStore.role === 'HOSPITAL_ADMIN') {
form.hospitalId = userStore.userInfo?.hospitalId || null;
@@ -460,9 +515,16 @@ const openCreateDialog = async () => {
await fetchDepartmentsForForm(form.hospitalId);
}
}
+
+ dialogVisible.value = true;
};
const openEditDialog = async (row) => {
+ if (isDirector.value && row.role !== 'DOCTOR') {
+ ElMessage.warning('主任仅可编辑本科室医生');
+ return;
+ }
+
isEdit.value = true;
currentId.value = row.id;
@@ -505,6 +567,31 @@ const resetForm = () => {
};
const buildSubmitPayload = () => {
+ if (isDirector.value) {
+ const directorScope = resolveDirectorScope();
+ if (!directorScope) {
+ return null;
+ }
+
+ const payload = {
+ name: form.name,
+ phone: form.phone,
+ role: 'DOCTOR',
+ hospitalId: directorScope.hospitalId,
+ departmentId: directorScope.departmentId,
+ groupId: form.groupId,
+ };
+
+ if (!isEdit.value) {
+ return {
+ ...payload,
+ password: form.password,
+ };
+ }
+
+ return payload;
+ }
+
const payload = {
name: form.name,
phone: form.phone,
@@ -575,6 +662,9 @@ const handleSubmit = async () => {
submitLoading.value = true;
try {
const payload = buildSubmitPayload();
+ if (!payload) {
+ return;
+ }
if (isEdit.value) {
await updateUser(currentId.value, payload);
ElMessage.success('更新成功');
@@ -592,6 +682,11 @@ const handleSubmit = async () => {
};
const handleDelete = (row) => {
+ if (isDirector.value && row.role !== 'DOCTOR') {
+ ElMessage.warning('主任仅可删除本科室医生');
+ return;
+ }
+
ElMessageBox.confirm(`确定要删除用户 "${row.name}" 吗?`, '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
@@ -698,16 +793,24 @@ onMounted(async () => {
if (route.query.action === 'create') {
await openCreateDialog();
- if (route.query.hospitalId) {
+ if (!isDirector.value && route.query.hospitalId) {
form.hospitalId = Number(route.query.hospitalId);
await fetchDepartmentsForForm(form.hospitalId);
}
- if (route.query.departmentId) {
+ if (!isDirector.value && route.query.departmentId) {
form.departmentId = Number(route.query.departmentId);
await fetchGroupsForForm(form.departmentId);
}
}
});
+
+const canDeleteUser = (row) => {
+ if (userStore.role === 'SYSTEM_ADMIN') {
+ return true;
+ }
+
+ return isDirector.value && row.role === 'DOCTOR';
+};