角色权限改为tree

This commit is contained in:
2026-05-09 14:47:20 +08:00
parent 8621178127
commit 616de27a3a
1 changed files with 85 additions and 178 deletions

View File

@ -8,95 +8,41 @@
<!-- 角色列表表格 --> <!-- 角色列表表格 -->
<RoleTable :table-data="roleTree" :columns="roleTableColumns" row-key="id"> <RoleTable :table-data="roleTree" :columns="roleTableColumns" row-key="id">
<template #status="{ row }"> <template #status="{ row }">
<el-switch <el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
:model-value="row.status === 1" inactive-text="禁用" />
:active-value="true"
:inactive-value="false"
active-text="启用"
inactive-text="禁用"
/>
</template> </template>
<template #createTime="{ row }"> <template #createTime="{ row }">
{{ row.created_at }} {{ row.created_at }}
</template> </template>
<template #action="{ row }"> <template #action="{ row }">
<el-button <el-button link type="primary" size="small" @click="handleEditRole(row)" v-auth="'roles_edit'">
link
type="primary"
size="small"
@click="handleEditRole(row)"
v-auth="'roles_edit'"
>
编辑 编辑
</el-button> </el-button>
<el-button <el-button link type="primary" size="small" @click="handlePermission(row)" v-auth="'roles_setPermission'">
link
type="primary"
size="small"
@click="handlePermission(row)"
v-auth="'roles_setPermission'"
>
设置权限 设置权限
</el-button> </el-button>
<el-button <el-button link type="danger" size="small" @click="handleDeleteRole(row)" v-auth="'roles_del'">
link
type="danger"
size="small"
@click="handleDeleteRole(row)"
v-auth="'roles_del'"
>
删除 删除
</el-button> </el-button>
</template> </template>
</RoleTable> </RoleTable>
</div> </div>
<!-- 角色新增/编辑弹窗 --> <!-- 角色新增/编辑抽屉 -->
<RoleDialog <el-drawer v-model="dialogVisible" :title="dialogTitle" :size="'800px'" @close="handleClose">
:visible="dialogVisible" <RoleForm :form-data="roleForm" :form-rules="roleFormRules" :form-items="roleFormItemOptions" ref="roleFormRef"
:title="dialogTitle" :options-map="roleFormOptionsMap" :dialog-type="dialogType">
:type="dialogType"
@confirm="handleSubmit"
@cancel="handleCancel"
@close="handleClose"
:fullscreen="fullScreen"
>
<RoleForm
:form-data="roleForm"
:form-rules="roleFormRules"
:form-items="roleFormItemOptions"
ref="roleFormRef"
:options-map="roleFormOptionsMap"
:dialog-type="dialogType"
>
<template #permissions="{ formData }"> <template #permissions="{ formData }">
<div class="permission-group"> <el-tree ref="permissionTreeRef" :data="permissionTreeData" :props="treeProps" show-checkbox node-key="id"
<div :default-checked-keys="formData.permissions" :default-expand-all="true" class="permission-tree" />
v-for="(group, module) in groupedPermissions"
:key="module"
class="permission-module"
>
<!-- 点击事件的 checked 参数 -->
<el-checkbox
:model-value="getModuleCheckedState(module)"
:indeterminate="getModuleIndeterminateState(module)"
@change="
(checked: boolean | string | number) => handleModuleCheckChange(module, !!checked)
"
class="module-title"
>
{{ module }}
</el-checkbox>
<!-- 添加子权限 change 事件监听 -->
<el-checkbox-group v-model="formData.permissions" @change="handlePermissionChange">
<el-checkbox v-for="perm in group" :key="perm.id" :value="perm.id">
{{ perm.title }} ({{ perm.name }})
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</template> </template>
</RoleForm> </RoleForm>
</RoleDialog> <template #footer>
<div style="flex: auto">
<el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleSubmit">确定</el-button>
</div>
</template>
</el-drawer>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
@ -104,7 +50,7 @@
defineOptions({ defineOptions({
name: 'Role' name: 'Role'
}) })
import type { FormInstance } from 'element-plus' import type { FormInstance, TreeInstance } from 'element-plus'
import { Plus } from '@element-plus/icons-vue' import { Plus } from '@element-plus/icons-vue'
// //
@ -123,6 +69,18 @@ import {
setRolePermissionApi, setRolePermissionApi,
} from '@/api/modules/system/role' } from '@/api/modules/system/role'
// Treeref
const permissionTreeRef = ref<TreeInstance>()
//
const permissionTreeData = ref<any[]>([])
// Treeprops
const treeProps = {
label: 'title',
children: 'children',
}
// header // header
const roleTitle = ref('角色管理') const roleTitle = ref('角色管理')
const roleHeaderButtons = [ const roleHeaderButtons = [
@ -154,10 +112,8 @@ const roleFormOptionsMap = ref({
permissions: [] as any[], permissions: [] as any[],
}) })
//id // id
const permissionIds = ref('') const permissionIds = ref('')
// { : [1,2...] }
const groupedPermissions = ref<Record<string, any[]>>({})
// //
const allPermissions = ref<any[]>([]) const allPermissions = ref<any[]>([])
@ -232,58 +188,42 @@ const handleDialogType = (type: string) => {
} }
} }
// //
const getModuleCheckedState = (module: string) => { const transformPermissionsToTree = (permissions: any[]) => {
const group = groupedPermissions.value[module] const moduleMap = new Map<string, any>()
if (!group) return false const childrenMap = new Map<string, any[]>()
const groupIds = group.map((perm) => perm.id)
return groupIds.every((id) => roleForm.value.permissions.includes(id))
}
// //
const getModuleIndeterminateState = (module: string) => {
const group = groupedPermissions.value[module]
if (!group) return false
const groupIds = group.map((perm) => perm.id)
const selectedCount = groupIds.filter((id) => roleForm.value.permissions.includes(id)).length
return selectedCount > 0 && selectedCount < group.length
}
// /
const handleModuleCheckChange = (module: string, checked: boolean) => {
const group = groupedPermissions.value[module]
if (!group) return
const groupIds = group.map((perm) => perm.id)
if (checked) {
roleForm.value.permissions = [...new Set([...roleForm.value.permissions, ...groupIds])]
} else {
roleForm.value.permissions = roleForm.value.permissions.filter((id) => !groupIds.includes(id))
}
}
//
const handlePermissionChange = () => {
roleForm.value = { ...roleForm.value }
}
// module
const groupPermissionsByModule = (permissions: any[]) => {
const grouped: Record<string, any[]> = {}
permissions.forEach((perm) => { permissions.forEach((perm) => {
grouped[perm.module] = grouped[perm.module] || [] if (perm.module && !moduleMap.has(perm.module)) {
const item = { //
...perm, const moduleItem = permissions.find((p) => p.title === perm.module)
pId: permissions.find((p) => p.title === perm.module).id, if (moduleItem) {
moduleMap.set(perm.module, {
id: moduleItem.id,
title: moduleItem.title,
children: [],
})
}
} }
grouped[perm.module]!.push(item)
}) })
for (const key in grouped) {
console.log(key, grouped[key]) //
grouped[key] = grouped[key].filter((item) => item.pId !== item.id) permissions.forEach((perm) => {
} if (perm.module && moduleMap.has(perm.module)) {
Object.values(grouped).forEach((group) => group.sort((a, b) => a.id - b.id)) const moduleItem = moduleMap.get(perm.module)!
return grouped //
if (perm.title !== perm.module) {
moduleItem.children.push({
id: perm.id,
title: `${perm.title} (${perm.name})`,
})
}
}
})
// ID
return Array.from(moduleMap.values()).sort((a, b) => a.id - b.id)
} }
// //
@ -295,13 +235,10 @@ const handlePermission = async (row: any) => {
permissionIds.value = row.id permissionIds.value = row.id
try { try {
const data = await getRolePermissionApi({ id: row.id }) const data = await getRolePermissionApi({ id: row.id })
allPermissions.value = data.all_permission_info.map((item) => ({ allPermissions.value = data.all_permission_info
...item, permissionTreeData.value = transformPermissionsToTree(data.all_permission_info)
pId: data.all_permission_info.find((p) => p.title === item.module)?.id,
}))
groupedPermissions.value = groupPermissionsByModule(data.all_permission_info)
roleForm.value.permissions = data.permission_ids || [] roleForm.value.permissions = data.permission_ids || []
console.log('分组后的权限', groupedPermissions.value) console.log('树形权限数据', permissionTreeData.value)
} catch (err) { } catch (err) {
console.error('获取角色权限失败', err) console.error('获取角色权限失败', err)
} }
@ -311,12 +248,7 @@ const handlePermission = async (row: any) => {
@description: 处理弹窗提交/取消/关闭事件 @description: 处理弹窗提交/取消/关闭事件
**/ **/
const handleSubmit = async () => { const handleSubmit = async () => {
console.log( console.log('提交菜单表单', roleForm.value.permissions, allPermissions.value)
'提交菜单表单',
roleForm.value.permissions,
groupedPermissions.value,
allPermissions.value,
) // ID便
try { try {
await roleFormRef.value?.validate() await roleFormRef.value?.validate()
if (dialogType.value === 'add') { if (dialogType.value === 'add') {
@ -330,19 +262,14 @@ const handleSubmit = async () => {
await editRoleApi(roleForm.value) await editRoleApi(roleForm.value)
await fetchRoleList() await fetchRoleList()
} else { } else {
let permissionIdList: any[] = [...roleForm.value.permissions] // Tree
for (let i = 0; i < allPermissions.value.length; i++) { const checkedKeys = permissionTreeRef.value?.getCheckedKeys() || []
const flag = permissionIdList.includes(allPermissions.value[i]!.id)
if (flag) { console.log('设置角色权限', checkedKeys.join(','))
if (!permissionIdList.includes(allPermissions.value[i]!.pId))
permissionIdList.push(allPermissions.value[i]!.pId)
}
}
console.log('设置角色权限', permissionIdList.join(','))
await setRolePermissionApi({ await setRolePermissionApi({
id: permissionIds.value, id: permissionIds.value,
permission_ids: permissionIdList.join(','), permission_ids: checkedKeys.join(','),
}) })
await fetchRoleList() await fetchRoleList()
} }
@ -377,42 +304,22 @@ const handleClose = () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.permission-group {
width: 100%;
}
:deep(.el-form-item__content) { :deep(.el-form-item__content) {
margin-left: 0 !important; margin-left: 0 !important;
} }
.system {
:deep(.el-drawer__header) {
margin-bottom: 0 !important;
}
}
.permission-module { .permission-tree {
margin-bottom: 20px; width: 100%;
border: 1px solid #e5e7eb; // border: 1px solid #e5e7eb;
border-radius: 6px; border-radius: 6px;
padding: 15px; // padding: 15px;
// max-height: 500px;
&:last-child { // overflow-y: auto;
margin-bottom: 0;
}
}
.module-title {
margin: 0 0 10px 0;
font-size: 16px;
font-weight: 600;
border-bottom: 1px solid #e5e7eb;
padding-bottom: 8px;
display: flex; // flex block
}
.permission-list {
display: flex;
flex-wrap: wrap;
gap: 15px;
}
.el-checkbox-group {
label {
margin-right: 15px;
}
} }
</style> </style>