角色权限改为tree
This commit is contained in:
parent
8621178127
commit
616de27a3a
|
|
@ -8,95 +8,41 @@
|
|||
<!-- 角色列表表格 -->
|
||||
<RoleTable :table-data="roleTree" :columns="roleTableColumns" row-key="id">
|
||||
<template #status="{ row }">
|
||||
<el-switch
|
||||
:model-value="row.status === 1"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
/>
|
||||
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
|
||||
inactive-text="禁用" />
|
||||
</template>
|
||||
<template #createTime="{ row }">
|
||||
{{ row.created_at }}
|
||||
</template>
|
||||
<template #action="{ row }">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleEditRole(row)"
|
||||
v-auth="'roles_edit'"
|
||||
>
|
||||
<el-button link type="primary" size="small" @click="handleEditRole(row)" v-auth="'roles_edit'">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handlePermission(row)"
|
||||
v-auth="'roles_setPermission'"
|
||||
>
|
||||
<el-button link type="primary" size="small" @click="handlePermission(row)" v-auth="'roles_setPermission'">
|
||||
设置权限
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="handleDeleteRole(row)"
|
||||
v-auth="'roles_del'"
|
||||
>
|
||||
<el-button link type="danger" size="small" @click="handleDeleteRole(row)" v-auth="'roles_del'">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</RoleTable>
|
||||
</div>
|
||||
<!-- 角色新增/编辑弹窗 -->
|
||||
<RoleDialog
|
||||
:visible="dialogVisible"
|
||||
:title="dialogTitle"
|
||||
: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"
|
||||
>
|
||||
<!-- 角色新增/编辑抽屉 -->
|
||||
<el-drawer v-model="dialogVisible" :title="dialogTitle" :size="'800px'" @close="handleClose">
|
||||
<RoleForm :form-data="roleForm" :form-rules="roleFormRules" :form-items="roleFormItemOptions" ref="roleFormRef"
|
||||
:options-map="roleFormOptionsMap" :dialog-type="dialogType">
|
||||
<template #permissions="{ formData }">
|
||||
<div class="permission-group">
|
||||
<div
|
||||
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>
|
||||
<el-tree ref="permissionTreeRef" :data="permissionTreeData" :props="treeProps" show-checkbox node-key="id"
|
||||
:default-checked-keys="formData.permissions" :default-expand-all="true" class="permission-tree" />
|
||||
</template>
|
||||
</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>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
@ -104,7 +50,7 @@
|
|||
defineOptions({
|
||||
name: 'Role'
|
||||
})
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import type { FormInstance, TreeInstance } from 'element-plus'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
|
||||
// 组件配置
|
||||
|
|
@ -123,6 +69,18 @@ import {
|
|||
setRolePermissionApi,
|
||||
} from '@/api/modules/system/role'
|
||||
|
||||
// Tree组件的ref
|
||||
const permissionTreeRef = ref<TreeInstance>()
|
||||
|
||||
// 树形数据
|
||||
const permissionTreeData = ref<any[]>([])
|
||||
|
||||
// Tree组件的props配置
|
||||
const treeProps = {
|
||||
label: 'title',
|
||||
children: 'children',
|
||||
}
|
||||
|
||||
// 定义header配置
|
||||
const roleTitle = ref('角色管理')
|
||||
const roleHeaderButtons = [
|
||||
|
|
@ -154,10 +112,8 @@ const roleFormOptionsMap = ref({
|
|||
permissions: [] as any[],
|
||||
})
|
||||
|
||||
//保存权限id
|
||||
// 保存权限id
|
||||
const permissionIds = ref('')
|
||||
// 分组后的权限 { 模块名: [权限1,权限2...] }
|
||||
const groupedPermissions = ref<Record<string, any[]>>({})
|
||||
// 原始权限列表
|
||||
const allPermissions = ref<any[]>([])
|
||||
|
||||
|
|
@ -232,58 +188,42 @@ const handleDialogType = (type: string) => {
|
|||
}
|
||||
}
|
||||
|
||||
// 获取模块全选状态(实时计算)
|
||||
const getModuleCheckedState = (module: string) => {
|
||||
const group = groupedPermissions.value[module]
|
||||
if (!group) return false
|
||||
const groupIds = group.map((perm) => perm.id)
|
||||
return groupIds.every((id) => roleForm.value.permissions.includes(id))
|
||||
}
|
||||
// 将权限数据转换为树形结构
|
||||
const transformPermissionsToTree = (permissions: any[]) => {
|
||||
const moduleMap = new Map<string, any>()
|
||||
const childrenMap = new Map<string, any[]>()
|
||||
|
||||
// 获取模块半选状态(实时计算)
|
||||
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) => {
|
||||
grouped[perm.module] = grouped[perm.module] || []
|
||||
const item = {
|
||||
...perm,
|
||||
pId: permissions.find((p) => p.title === perm.module).id,
|
||||
if (perm.module && !moduleMap.has(perm.module)) {
|
||||
// 找到该模块对应的权限项作为父节点
|
||||
const moduleItem = permissions.find((p) => p.title === perm.module)
|
||||
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)
|
||||
}
|
||||
Object.values(grouped).forEach((group) => group.sort((a, b) => a.id - b.id))
|
||||
return grouped
|
||||
|
||||
// 将权限项归类到对应的模块下
|
||||
permissions.forEach((perm) => {
|
||||
if (perm.module && moduleMap.has(perm.module)) {
|
||||
const moduleItem = moduleMap.get(perm.module)!
|
||||
// 排除模块本身,只添加子权限
|
||||
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
|
||||
try {
|
||||
const data = await getRolePermissionApi({ id: row.id })
|
||||
allPermissions.value = data.all_permission_info.map((item) => ({
|
||||
...item,
|
||||
pId: data.all_permission_info.find((p) => p.title === item.module)?.id,
|
||||
}))
|
||||
groupedPermissions.value = groupPermissionsByModule(data.all_permission_info)
|
||||
allPermissions.value = data.all_permission_info
|
||||
permissionTreeData.value = transformPermissionsToTree(data.all_permission_info)
|
||||
roleForm.value.permissions = data.permission_ids || []
|
||||
console.log('分组后的权限', groupedPermissions.value)
|
||||
console.log('树形权限数据', permissionTreeData.value)
|
||||
} catch (err) {
|
||||
console.error('获取角色权限失败', err)
|
||||
}
|
||||
|
|
@ -311,12 +248,7 @@ const handlePermission = async (row: any) => {
|
|||
@description: 处理弹窗提交/取消/关闭事件
|
||||
**/
|
||||
const handleSubmit = async () => {
|
||||
console.log(
|
||||
'提交菜单表单',
|
||||
roleForm.value.permissions,
|
||||
groupedPermissions.value,
|
||||
allPermissions.value,
|
||||
) // 新增:打印选中的权限ID,便于调试
|
||||
console.log('提交菜单表单', roleForm.value.permissions, allPermissions.value)
|
||||
try {
|
||||
await roleFormRef.value?.validate()
|
||||
if (dialogType.value === 'add') {
|
||||
|
|
@ -330,19 +262,14 @@ const handleSubmit = async () => {
|
|||
await editRoleApi(roleForm.value)
|
||||
await fetchRoleList()
|
||||
} else {
|
||||
let permissionIdList: any[] = [...roleForm.value.permissions]
|
||||
for (let i = 0; i < allPermissions.value.length; i++) {
|
||||
const flag = permissionIdList.includes(allPermissions.value[i]!.id)
|
||||
if (flag) {
|
||||
if (!permissionIdList.includes(allPermissions.value[i]!.pId))
|
||||
permissionIdList.push(allPermissions.value[i]!.pId)
|
||||
}
|
||||
}
|
||||
console.log('设置角色权限', permissionIdList.join(','))
|
||||
// 获取Tree组件选中的所有节点(不包括半选节点)
|
||||
const checkedKeys = permissionTreeRef.value?.getCheckedKeys() || []
|
||||
|
||||
console.log('设置角色权限', checkedKeys.join(','))
|
||||
|
||||
await setRolePermissionApi({
|
||||
id: permissionIds.value,
|
||||
permission_ids: permissionIdList.join(','),
|
||||
permission_ids: checkedKeys.join(','),
|
||||
})
|
||||
await fetchRoleList()
|
||||
}
|
||||
|
|
@ -377,42 +304,22 @@ const handleClose = () => {
|
|||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.permission-group {
|
||||
width: 100%;
|
||||
}
|
||||
:deep(.el-form-item__content) {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.system {
|
||||
:deep(.el-drawer__header) {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.permission-module {
|
||||
margin-bottom: 20px;
|
||||
border: 1px solid #e5e7eb;
|
||||
.permission-tree {
|
||||
width: 100%;
|
||||
// border: 1px solid #e5e7eb;
|
||||
border-radius: 6px;
|
||||
padding: 15px;
|
||||
|
||||
&:last-child {
|
||||
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;
|
||||
}
|
||||
// padding: 15px;
|
||||
// max-height: 500px;
|
||||
// overflow-y: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in New Issue