Skip to content

Commit 1d6ed14

Browse files
committed
feat: enhance role management with improved permission structure and category mapping
1 parent 6128801 commit 1d6ed14

6 files changed

Lines changed: 192 additions & 130 deletions

File tree

‎apps/common/auth/constants/permission_constants.py‎

Lines changed: 142 additions & 117 deletions
Large diffs are not rendered by default.

‎apps/common/auth/struct/permission.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class PermissionMeta:
5151
category: Optional[Category] = None
5252
resource_permission_group_list: Optional[list] = None
5353
scope: list[PermissionScopeConstants] = field(default_factory=list)
54-
is_ee: bool = False
54+
is_ee: bool = True
55+
# 角色 -> 分类 覆盖表;未列出的角色默认归入 OTHER
56+
role_category_map: Optional[dict] = None
5557

5658

5759
@dataclass(frozen=True)

‎ui/src/api/admin/system/role.ts‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import { del, get, post } from '../core/request'
22
import type { ParamsPage, ResponsePage } from '../core/types'
3-
import type { CreateRoleMembersRequest, Dict, RoleItem, RoleMember, RolePermissionModule, RolePayload, SaveRolePermissionRequest } from '@/api/types'
3+
import type { CreateRoleMembersRequest, Dict, RoleItem, RoleMember, RolePermissionModule, RolePayload, RoleType, SaveRolePermissionRequest } from '@/api/types'
44

55
const prefix = '/system/role'
66

77
/** 获取内置角色与自定义角色列表。 */
88
const getRoleList = () => {
9-
return get<{ internal_role: RoleItem[]; custom_role: RoleItem[] }>(prefix)
9+
return get<{ internal_role: RoleItem[]; custom_role: RoleItem[] } | Array<{ role_type: RoleType; role_list: RoleItem[] }>>(prefix).then((data) => {
10+
if (Array.isArray(data)) {
11+
// 后端按角色类型分组返回 { role_type, role_list },展平为扁平角色数组
12+
return data.flatMap((group) => group.role_list ?? [])
13+
}
14+
return [...(data.internal_role ?? []), ...(data.custom_role ?? [])]
15+
})
1016
}
1117

1218
/** 创建或重命名自定义角色。 */

‎ui/src/api/types/system-role.ts‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,22 @@ export interface RolePermission {
2020
export interface RolePermissionFeature {
2121
id: string
2222
name: string
23-
enable: boolean
23+
enable?: boolean
2424
permission: RolePermission[]
2525
}
2626

27-
export interface RolePermissionModule {
27+
export interface RolePermissionModuleGroup {
2828
id: string
2929
name: string
3030
children: RolePermissionFeature[]
3131
}
3232

33+
export interface RolePermissionModule {
34+
id: string
35+
name: string
36+
children: RolePermissionModuleGroup[]
37+
}
38+
3339
export interface RolePayload {
3440
role_id?: string
3541
role_name: string

‎ui/src/views/system/identity/roles/RoleListView.vue‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ const roleGroups = computed(() => {
3030
function loadRoles(selectedRoleId?: string) {
3131
loadingRoles.value = true
3232
return RoleApi.getRoleList()
33-
.then(({ internal_role, custom_role }) => {
34-
AllRoles.value = [...internal_role, ...custom_role]
33+
.then((roles) => {
34+
AllRoles.value = roles
3535
currentRole.value =
36-
AllRoles.value.find(({ id }) => id === selectedRoleId) ?? AllRoles.value.find(({ id }) => id === currentRole.value?.id) ?? internal_role[0]
36+
AllRoles.value.find(({ id }) => id === selectedRoleId) ?? AllRoles.value.find(({ id }) => id === currentRole.value?.id) ?? AllRoles.value[0]
3737
})
3838
.finally(() => {
3939
loadingRoles.value = false

‎ui/src/views/system/identity/roles/components/RolePermissionConfiguration.vue‎

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { MsgSuccess } from '@/utils/message'
66
77
interface PermissionTableRow {
88
id: string
9+
categoryId: string
10+
category: string
911
moduleId: string
1012
module: string
1113
name: string
@@ -30,15 +32,35 @@ function loadPermissions() {
3032
}
3133
3234
function transformPermissions(modules: RolePermissionModule[]) {
33-
return modules.flatMap((module) =>
34-
module.children.map((feature) => ({ id: `${module.id}:${feature.id}`, moduleId: module.id, module: module.name, name: feature.name, permissions: feature.permission })),
35+
// 后端返回 分类(category) → 分组(group) → 叶子(feature) → 权限 的结构,
36+
// 分类 → “分类”列,分组 → “模块名称”列,叶子 → “操作对象”列,向下展平为表格行
37+
return modules.flatMap((category) =>
38+
category.children.flatMap((group) =>
39+
group.children.map((feature) => ({
40+
id: `${category.id}:${group.id}:${feature.id}`,
41+
categoryId: category.id,
42+
category: category.name,
43+
moduleId: `${category.id}:${group.id}`,
44+
module: group.name,
45+
name: feature.name,
46+
permissions: feature.permission,
47+
})),
48+
),
3549
)
3650
}
3751
3852
function permissionTableSpan({ row, rowIndex, columnIndex }: { row: PermissionTableRow; rowIndex: number; columnIndex: number }) {
39-
if (columnIndex !== 0) return [1, 1]
40-
const firstRowIndex = permissionData.value.findIndex(({ moduleId }) => moduleId === row.moduleId)
41-
return rowIndex === firstRowIndex ? [permissionData.value.filter(({ moduleId }) => moduleId === row.moduleId).length, 1] : [0, 0]
53+
if (columnIndex === 0) {
54+
// “分类”列按分类纵向合并
55+
const firstRowIndex = permissionData.value.findIndex(({ categoryId }) => categoryId === row.categoryId)
56+
return rowIndex === firstRowIndex ? [permissionData.value.filter(({ categoryId }) => categoryId === row.categoryId).length, 1] : [0, 0]
57+
}
58+
if (columnIndex === 1) {
59+
// “模块名称”列按分组纵向合并
60+
const firstRowIndex = permissionData.value.findIndex(({ moduleId }) => moduleId === row.moduleId)
61+
return rowIndex === firstRowIndex ? [permissionData.value.filter(({ moduleId }) => moduleId === row.moduleId).length, 1] : [0, 0]
62+
}
63+
return [1, 1]
4264
}
4365
4466
/* 单项权限与查看权限联动 */
@@ -96,6 +118,7 @@ watch(() => props.currentRole.id, loadPermissions, { immediate: true })
96118
:data="permissionData"
97119
v-loading="loading"
98120
>
121+
<el-table-column prop="category" label="分类" width="120" />
99122
<el-table-column prop="module" label="模块名称" width="150" />
100123
<el-table-column prop="name" label="操作对象" width="150" />
101124
<el-table-column label="权限">

0 commit comments

Comments
 (0)