From 757145506e8a1239a41fca6ba49ff9ccd0f2a838 Mon Sep 17 00:00:00 2001 From: xy Date: Thu, 24 Sep 2026 20:37:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(role):=20=E5=B1=95=E7=A4=BA=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E4=BA=BA=E5=91=98=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clinical-web/src/api/management/roles.ts | 23 ++- clinical-web/src/api/management/types.ts | 9 + .../src/views/management/roles/index.vue | 167 +++++++++++++++++- 3 files changed, 194 insertions(+), 5 deletions(-) diff --git a/clinical-web/src/api/management/roles.ts b/clinical-web/src/api/management/roles.ts index 90397ca..d09f43e 100644 --- a/clinical-web/src/api/management/roles.ts +++ b/clinical-web/src/api/management/roles.ts @@ -1,13 +1,15 @@ import { unwrapApiResponse, unwrapNullableApiResponse } from '@/utils/api-response' import { request } from '@/utils/request' -import type { ApiResponse } from '@/types/common' +import type { ApiResponse, PageResult } from '@/types/common' import type { BackendCollection, + BackendPage, CreateRoleRequest, PermissionResourceNodeDto, RoleDataScopeRequest, RoleDataScopeResponseDto, + RoleMemberDto, RoleRecord, RoleResponseDto, UpdateRoleRequest, @@ -21,6 +23,7 @@ function normalizeRole(dto: RoleResponseDto, index: number): RoleRecord { code: dto.code, name: dto.name, description: dto.description ?? '', + userCount: dto.userCount ?? 0, color: fallbackColors[index % fallbackColors.length], status: dto.status ?? 'DISABLED', menuPermissionCount: dto.menuPermissionCount ?? 0, @@ -50,6 +53,24 @@ export async function getAssignableRoles(): Promise { return normalizeCollection(unwrapApiResponse(response)).map(normalizeRole) } +export async function getRoleMembers( + roleId: string, + page: number, + pageSize: number, +): Promise> { + const response = await request.get>>( + `/v1/roles/${encodeURIComponent(roleId)}/users`, + { params: { page, size: pageSize } }, + ) + const result = unwrapApiResponse(response) + return { + records: result.records ?? result.items ?? result.content ?? [], + total: result.total ?? 0, + page: result.page ?? page, + pageSize: result.size ?? pageSize, + } +} + export async function getRolePermissionTree(): Promise { const response = await request.get>( '/v1/roles/permission-tree', diff --git a/clinical-web/src/api/management/types.ts b/clinical-web/src/api/management/types.ts index ea7689f..3d3108c 100644 --- a/clinical-web/src/api/management/types.ts +++ b/clinical-web/src/api/management/types.ts @@ -166,6 +166,7 @@ export interface RoleResponseDto { code: string name: string description?: string | null + userCount?: number | null status?: RoleStatus | null menuPermissionCount?: number | null buttonPermissionCount?: number | null @@ -176,6 +177,14 @@ export interface RoleResponseDto { version?: number | null } +export interface RoleMemberDto { + id: string + employeeId?: number | null + displayName: string + employeeNo?: string | null + campusName?: string | null +} + export interface CreateRoleRequest { code: string name: string diff --git a/clinical-web/src/views/management/roles/index.vue b/clinical-web/src/views/management/roles/index.vue index d6ff95e..98e9620 100644 --- a/clinical-web/src/views/management/roles/index.vue +++ b/clinical-web/src/views/management/roles/index.vue @@ -6,6 +6,7 @@ import { getAllDepartments, getCampuses } from '@/api/management/organization' import { createRole, deleteRole, + getRoleMembers, getRoleDataScope, getRolePermissionTree, getRolePermissions, @@ -20,6 +21,7 @@ import type { DepartmentRecord, PermissionResourceNodeDto, RoleDataScopeType, + RoleMemberDto, RoleRecord, } from '@/api/management/types' import { useLoginStore } from '@/stores/login' @@ -27,6 +29,13 @@ import { useLoginStore } from '@/stores/login' const loginStore = useLoginStore() const loading = ref(false) const roles = ref([]) +const selectedRoleId = ref('') +const roleMembers = ref([]) +const membersLoading = ref(false) +const memberPage = ref(1) +const memberPageSize = 10 +const memberTotal = ref(0) +let memberRequestSequence = 0 const keyword = ref('') const formVisible = ref(false) const formSaving = ref(false) @@ -74,6 +83,9 @@ const filteredRoles = computed(() => { role.code.toLocaleLowerCase().includes(query), ) }) +const selectedRole = computed( + () => roles.value.find((role) => role.id === selectedRoleId.value) ?? null, +) const scopeLabels: Record = { ALL: '全院', CUSTOM: '指定院区 / 科室', @@ -132,14 +144,62 @@ async function loadRoles() { loading.value = true try { roles.value = await getRoles() + const nextRole = roles.value.find((role) => role.id === selectedRoleId.value) ?? roles.value[0] + if (nextRole) { + await loadRoleMembers( + nextRole.id, + nextRole.id === selectedRoleId.value ? memberPage.value : 1, + ) + } else { + memberRequestSequence += 1 + selectedRoleId.value = '' + roleMembers.value = [] + memberTotal.value = 0 + membersLoading.value = false + } } catch { + memberRequestSequence += 1 roles.value = [] + selectedRoleId.value = '' + roleMembers.value = [] + memberTotal.value = 0 + membersLoading.value = false ElMessage.error('角色列表加载失败,请检查当前账号权限') } finally { loading.value = false } } +async function loadRoleMembers(roleId: string, page = 1) { + const requestSequence = ++memberRequestSequence + selectedRoleId.value = roleId + memberPage.value = page + membersLoading.value = true + try { + const result = await getRoleMembers(roleId, page, memberPageSize) + if (requestSequence !== memberRequestSequence) return + roleMembers.value = result.records + memberTotal.value = result.total + memberPage.value = result.page + } catch { + if (requestSequence !== memberRequestSequence) return + roleMembers.value = [] + memberTotal.value = 0 + ElMessage.error('角色成员加载失败,请检查当前账号权限') + } finally { + if (requestSequence === memberRequestSequence) membersLoading.value = false + } +} + +function selectRole(role: RoleRecord) { + if (selectedRoleId.value === role.id) return + void loadRoleMembers(role.id) +} + +function handleMemberPageChange(page: number) { + if (selectedRole.value) void loadRoleMembers(selectedRole.value.id, page) +} + function isSystemAdmin(role: RoleRecord) { return role.code === 'SYSTEM_ADMIN' } @@ -429,10 +489,21 @@ onMounted(loadRoles) - + - {{ role.name }}内置 + {{ role.name }} + 内置 + {{ role.userCount ?? 0 }} 人 {{ role.code }} @@ -448,7 +519,7 @@ onMounted(loadRoles) {{ role.menuPermissionCount }} {{ role.buttonPermissionCount }} {{ scopeLabels[role.dataScope] ?? '未配置' }} - +