From a97d317e4afa2856dd2b0f8ff5174449c7d3721a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E7=BF=94?= Date: Fri, 20 Mar 2026 08:02:03 +0800 Subject: [PATCH] refactor: RoleManagement component with API services and permission assignment --- .../src/views/system/RoleManagement.vue | 238 ++++++++++++++---- 1 file changed, 194 insertions(+), 44 deletions(-) diff --git a/novalon-manage-web/src/views/system/RoleManagement.vue b/novalon-manage-web/src/views/system/RoleManagement.vue index c5da991..e79dd5d 100644 --- a/novalon-manage-web/src/views/system/RoleManagement.vue +++ b/novalon-manage-web/src/views/system/RoleManagement.vue @@ -40,27 +40,30 @@ - + @@ -71,7 +74,7 @@ /> + + + + + @@ -153,10 +202,11 @@ import { ref, reactive, onMounted } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { Search } from '@element-plus/icons-vue' -import request from '@/utils/request' +import { roleApi, type Role, type CreateRoleRequest, type UpdateRoleRequest, type Permission } from '@/api/role.api' +import { handleApiError } from '@/utils/errorHandler' const loading = ref(false) -const dataSource = ref([]) +const dataSource = ref([]) const searchKeyword = ref('') const pagination = reactive({ current: 1, @@ -165,28 +215,40 @@ const pagination = reactive({ }) const sortInfo = reactive({ - sort: 'id', - order: 'asc' + sortBy: 'id', + sortOrder: 'asc' as 'asc' | 'desc' }) const modalVisible = ref(false) const modalTitle = ref('') -const formState = reactive({ id: null, roleName: '', roleKey: '', roleSort: 0, status: '0' }) +const formState = reactive({ + name: '', + code: '', + description: '', + permissions: [], + status: 'ACTIVE' +}) + +const permissionDialogVisible = ref(false) +const permissionTreeRef = ref() +const permissionTree = ref([]) +const selectedPermissions = ref([]) +const currentRoleId = ref(null) const fetchData = async () => { loading.value = true try { - const res: any = await request.get('/roles/page', { - params: { - page: pagination.current - 1, - size: pagination.pageSize, - sort: sortInfo.sort, - order: sortInfo.order, - keyword: searchKeyword.value || undefined - } + const res = await roleApi.getPage({ + page: pagination.current - 1, + size: pagination.pageSize, + sortBy: sortInfo.sortBy, + sortOrder: sortInfo.sortOrder, + name: searchKeyword.value || undefined }) dataSource.value = res.content pagination.total = res.totalElements + } catch (error) { + handleApiError(error) } finally { loading.value = false } @@ -207,54 +269,142 @@ const handleSearch = () => { } const handleSortChange = ({ prop, order }: any) => { - sortInfo.sort = prop - sortInfo.order = order === 'ascending' ? 'asc' : 'desc' + sortInfo.sortBy = prop + sortInfo.sortOrder = order === 'ascending' ? 'asc' : 'desc' fetchData() } const handleAdd = () => { modalTitle.value = '新增角色' - Object.assign(formState, { id: null, roleName: '', roleKey: '', roleSort: 0, status: '0' }) + Object.assign(formState, { + id: undefined, + name: '', + code: '', + description: '', + permissions: [], + status: 'ACTIVE' + }) modalVisible.value = true } -const handleEdit = (row: any) => { +const handleEdit = (row: Role) => { modalTitle.value = '编辑角色' - Object.assign(formState, row) + Object.assign(formState, { + id: row.id, + name: row.name, + code: row.code, + description: row.description, + status: row.status, + permissions: [] + }) modalVisible.value = true } -const handleDelete = async (row: any) => { +const handleDelete = async (row: Role) => { try { await ElMessageBox.confirm('确定要删除该角色吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }) - await request.delete(`/roles/${row.id}`) + await roleApi.delete(row.id) ElMessage.success('删除成功') fetchData() } catch (error) { - console.error('删除角色失败:', error) + if (error !== 'cancel') { + handleApiError(error) + } } } const handleModalOk = async () => { try { if (formState.id) { - await request.put(`/roles/${formState.id}`, formState) + const updateData: UpdateRoleRequest = { + name: formState.name, + description: formState.description, + status: formState.status as 'ACTIVE' | 'INACTIVE' + } + await roleApi.update(formState.id, updateData) + ElMessage.success('更新成功') } else { - await request.post('/roles', formState) + const createData: CreateRoleRequest = { + name: formState.name, + code: formState.code, + description: formState.description, + permissions: formState.permissions + } + await roleApi.create(createData) + ElMessage.success('创建成功') } - ElMessage.success('操作成功') modalVisible.value = false fetchData() - } catch { - ElMessage.error('操作失败') + } catch (error) { + handleApiError(error) } } -onMounted(() => fetchData()) +const handleAssignPermissions = async (row: Role) => { + currentRoleId.value = row.id + try { + const allPermissions = await roleApi.getAllPermissions() + permissionTree.value = buildPermissionTree(allPermissions) + + const rolePermissions = await roleApi.getPermissions(row.id) + selectedPermissions.value = rolePermissions.map((p: Permission) => p.id) + + permissionDialogVisible.value = true + } catch (error) { + handleApiError(error) + } +} + +const buildPermissionTree = (permissions: Permission[]): any[] => { + const tree: any[] = [] + const resourceMap = new Map() + + permissions.forEach(p => { + if (!resourceMap.has(p.resource)) { + resourceMap.set(p.resource, []) + } + resourceMap.get(p.resource)!.push(p) + }) + + resourceMap.forEach((perms, resource) => { + tree.push({ + id: `resource-${resource}`, + name: resource, + children: perms.map(p => ({ + id: p.id, + name: p.name + })) + }) + }) + + return tree +} + +const handleAssignPermissionsOk = async () => { + if (!currentRoleId.value) return + + try { + const checkedNodes = permissionTreeRef.value.getCheckedNodes() + const permissionIds = checkedNodes + .filter((node: any) => typeof node.id === 'number') + .map((node: any) => node.id) + + await roleApi.assignPermissions(currentRoleId.value, permissionIds) + ElMessage.success('权限分配成功') + permissionDialogVisible.value = false + fetchData() + } catch (error) { + handleApiError(error) + } +} + +onMounted(() => { + fetchData() +})