fetch(modify):修改bug
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 6m6s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 6m6s
This commit is contained in:
@@ -88,39 +88,71 @@
|
||||
</ElDialog>
|
||||
|
||||
<!-- 分配权限对话框 -->
|
||||
<ElDialog v-model="permissionDialogVisible" title="分配权限" width="500px">
|
||||
<ElTree
|
||||
ref="permissionTreeRef"
|
||||
:data="permissionTreeData"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:default-checked-keys="selectedPermissions"
|
||||
:props="{ children: 'children', label: 'label' }"
|
||||
:default-expand-all="false"
|
||||
class="permission-tree"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span style="display: flex; align-items: center; gap: 8px">
|
||||
<span>{{ node.label }}</span>
|
||||
<ElTag
|
||||
:type="data.perm_type === 1 ? 'info' : 'success'"
|
||||
size="small"
|
||||
<ElDialog v-model="permissionDialogVisible" title="分配权限" width="800px">
|
||||
<div class="permission-assignment-container">
|
||||
<!-- 左侧:权限树(用于添加) -->
|
||||
<div class="permission-tree-section">
|
||||
<div class="section-title">可分配权限</div>
|
||||
<ElTree
|
||||
ref="permissionTreeRef"
|
||||
:data="permissionTreeData"
|
||||
show-checkbox
|
||||
node-key="id"
|
||||
:props="{ children: 'children', label: 'label' }"
|
||||
:default-expand-all="false"
|
||||
class="permission-tree"
|
||||
@check="handlePermissionCheck"
|
||||
>
|
||||
<template #default="{ node, data }">
|
||||
<span style="display: flex; align-items: center; gap: 8px">
|
||||
<span>{{ node.label }}</span>
|
||||
<ElTag
|
||||
:type="data.perm_type === 1 ? 'info' : 'success'"
|
||||
size="small"
|
||||
>
|
||||
{{ data.perm_type === 1 ? '菜单' : '按钮' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
</template>
|
||||
</ElTree>
|
||||
</div>
|
||||
|
||||
<!-- 右侧:已分配权限列表 -->
|
||||
<div class="assigned-permissions-section">
|
||||
<div class="section-title">已分配权限</div>
|
||||
<div class="assigned-list">
|
||||
<div
|
||||
v-for="perm in assignedPermissionsList"
|
||||
:key="perm.id"
|
||||
class="assigned-item"
|
||||
>
|
||||
{{ data.perm_type === 1 ? '菜单' : '按钮' }}
|
||||
</ElTag>
|
||||
</span>
|
||||
</template>
|
||||
</ElTree>
|
||||
<ElTag
|
||||
:type="perm.perm_type === 1 ? 'info' : 'success'"
|
||||
size="small"
|
||||
>
|
||||
{{ perm.perm_type === 1 ? '菜单' : '按钮' }}
|
||||
</ElTag>
|
||||
<span class="perm-name">{{ perm.perm_name }}</span>
|
||||
<ElButton
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="removePermission(perm.id)"
|
||||
>
|
||||
移除
|
||||
</ElButton>
|
||||
</div>
|
||||
<ElEmpty
|
||||
v-if="assignedPermissionsList.length === 0"
|
||||
description="暂无已分配权限"
|
||||
:image-size="80"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<ElButton @click="permissionDialogVisible = false">取消</ElButton>
|
||||
<ElButton
|
||||
type="primary"
|
||||
@click="handleAssignPermissions"
|
||||
:loading="permissionSubmitLoading"
|
||||
>
|
||||
提交
|
||||
</ElButton>
|
||||
<ElButton @click="permissionDialogVisible = false">关闭</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ElDialog>
|
||||
@@ -140,7 +172,7 @@
|
||||
ElSwitch
|
||||
} from 'element-plus'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import type { PlatformRole, Permission } from '@/types/api'
|
||||
import type { PlatformRole, PermissionTreeNode } from '@/types/api'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
@@ -162,8 +194,10 @@
|
||||
const currentRoleId = ref<number>(0)
|
||||
const selectedPermissions = ref<number[]>([])
|
||||
const originalPermissions = ref<number[]>([]) // 保存原始权限,用于对比
|
||||
const allPermissions = ref<Permission[]>([])
|
||||
const permissionTreeData = ref<any[]>([])
|
||||
const assignedPermissionsList = ref<any[]>([]) // 已分配的权限列表(用于右侧显示)
|
||||
const allPermissionsFlat = ref<PermissionTreeNode[]>([]) // 扁平化的所有权限数据
|
||||
const isInitializingTree = ref(false) // 标记是否正在初始化树的选中状态
|
||||
|
||||
// 搜索表单初始值
|
||||
const initialSearchState = {
|
||||
@@ -319,73 +353,62 @@
|
||||
|
||||
onMounted(() => {
|
||||
getTableData()
|
||||
loadAllPermissions()
|
||||
})
|
||||
|
||||
// 将扁平数据转换为树形结构
|
||||
const buildTreeData = (flatData: Permission[]): any[] => {
|
||||
const map = new Map<number, any>()
|
||||
const result: any[] = []
|
||||
|
||||
// 先创建所有节点的映射
|
||||
flatData.forEach((item) => {
|
||||
map.set(item.ID, {
|
||||
id: item.ID,
|
||||
label: item.perm_name,
|
||||
perm_type: item.perm_type,
|
||||
children: []
|
||||
})
|
||||
})
|
||||
|
||||
// 构建树形结构
|
||||
flatData.forEach((item) => {
|
||||
const node = map.get(item.ID)!
|
||||
if (item.parent_id && map.has(item.parent_id)) {
|
||||
const parent = map.get(item.parent_id)!
|
||||
parent.children.push(node)
|
||||
} else {
|
||||
// 没有父节点的是根节点
|
||||
// 将权限树扁平化为一维数组
|
||||
const flattenPermissionTree = (treeNodes: PermissionTreeNode[]): PermissionTreeNode[] => {
|
||||
const result: PermissionTreeNode[] = []
|
||||
const flatten = (nodes: PermissionTreeNode[]) => {
|
||||
nodes.forEach((node) => {
|
||||
result.push(node)
|
||||
}
|
||||
})
|
||||
|
||||
// 递归排序和清理空children
|
||||
const sortAndCleanTree = (nodes: any[]): any[] => {
|
||||
return nodes
|
||||
.sort((a, b) => {
|
||||
const aItem = flatData.find((p) => p.ID === a.id)
|
||||
const bItem = flatData.find((p) => p.ID === b.id)
|
||||
return (aItem?.sort || 0) - (bItem?.sort || 0)
|
||||
})
|
||||
.map((node) => ({
|
||||
...node,
|
||||
children:
|
||||
node.children && node.children.length > 0 ? sortAndCleanTree(node.children) : undefined
|
||||
}))
|
||||
if (node.children && node.children.length > 0) {
|
||||
flatten(node.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return sortAndCleanTree(result)
|
||||
flatten(treeNodes)
|
||||
return result
|
||||
}
|
||||
|
||||
// 加载所有权限列表
|
||||
// 将权限树节点转换为ElTree所需的格式
|
||||
const buildTreeData = (treeNodes: PermissionTreeNode[]): any[] => {
|
||||
return treeNodes.map((node) => ({
|
||||
id: node.id,
|
||||
label: node.perm_name,
|
||||
perm_type: node.perm_type,
|
||||
children: node.children && node.children.length > 0 ? buildTreeData(node.children) : undefined
|
||||
}))
|
||||
}
|
||||
|
||||
// 加载所有权限树
|
||||
const loadAllPermissions = async () => {
|
||||
try {
|
||||
const res = await PermissionService.getPermissions({ page: 1, page_size: 1000 })
|
||||
const res = await PermissionService.getPermissionTree()
|
||||
if (res.code === 0) {
|
||||
allPermissions.value = res.data.items || []
|
||||
const treeData = res.data || []
|
||||
// 扁平化所有权限数据,用于查找
|
||||
allPermissionsFlat.value = flattenPermissionTree(treeData)
|
||||
// 构建树形数据
|
||||
permissionTreeData.value = buildTreeData(allPermissions.value)
|
||||
permissionTreeData.value = buildTreeData(treeData)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取权限列表失败:', error)
|
||||
console.error('获取权限树失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 根据权限ID列表构建已分配权限列表
|
||||
const buildAssignedPermissionsList = () => {
|
||||
assignedPermissionsList.value = selectedPermissions.value
|
||||
.map((id) => allPermissionsFlat.value.find((p) => p.id === id))
|
||||
.filter((p) => p !== undefined) as PermissionTreeNode[]
|
||||
}
|
||||
|
||||
// 显示分配权限对话框
|
||||
const showPermissionDialog = async (row: PlatformRole) => {
|
||||
currentRoleId.value = row.ID
|
||||
selectedPermissions.value = []
|
||||
originalPermissions.value = []
|
||||
assignedPermissionsList.value = []
|
||||
|
||||
try {
|
||||
// 每次打开对话框时重新加载最新的权限列表
|
||||
@@ -393,75 +416,136 @@
|
||||
|
||||
// 加载当前角色的权限
|
||||
const res = await RoleService.getRolePermissions(row.ID)
|
||||
|
||||
if (res.code === 0 || Array.isArray(res.data)) {
|
||||
// 提取权限ID数组
|
||||
const permissions = res.data || []
|
||||
|
||||
if (Array.isArray(permissions) && permissions.length > 0) {
|
||||
// 如果返回的是权限对象数组,提取ID
|
||||
if (typeof permissions[0] === 'object' && 'ID' in permissions[0]) {
|
||||
selectedPermissions.value = permissions.map((perm: any) => perm.ID)
|
||||
// 如果返回的是权限对象数组,提取ID或id字段
|
||||
if (typeof permissions[0] === 'object') {
|
||||
// 优先使用ID字段,如果没有则使用id字段
|
||||
if ('ID' in permissions[0]) {
|
||||
selectedPermissions.value = permissions.map((perm: any) => perm.ID)
|
||||
} else if ('id' in permissions[0]) {
|
||||
selectedPermissions.value = permissions.map((perm: any) => perm.id)
|
||||
}
|
||||
} else {
|
||||
// 如果返回的是ID数组
|
||||
selectedPermissions.value = permissions
|
||||
}
|
||||
}
|
||||
|
||||
// 保存原始权限,用于后续对比
|
||||
originalPermissions.value = [...selectedPermissions.value]
|
||||
|
||||
// 构建已分配权限列表
|
||||
buildAssignedPermissionsList()
|
||||
|
||||
// 数据加载完成后再打开对话框
|
||||
permissionDialogVisible.value = true
|
||||
|
||||
// 等待DOM更新后设置树的初始选中状态
|
||||
await nextTick()
|
||||
if (permissionTreeRef.value) {
|
||||
isInitializingTree.value = true
|
||||
permissionTreeRef.value.setCheckedKeys(selectedPermissions.value, false)
|
||||
// 延迟一点时间后取消初始化标记
|
||||
setTimeout(() => {
|
||||
isInitializingTree.value = false
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取角色权限失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// 提交分配权限
|
||||
const handleAssignPermissions = async () => {
|
||||
// 处理权限勾选(只允许添加,不允许取消)
|
||||
const handlePermissionCheck = async (data: any, checkedInfo: any) => {
|
||||
if (!permissionTreeRef.value) return
|
||||
|
||||
permissionSubmitLoading.value = true
|
||||
try {
|
||||
// 获取选中的节点(包括半选中的父节点)
|
||||
const checkedKeys = permissionTreeRef.value.getCheckedKeys()
|
||||
const halfCheckedKeys = permissionTreeRef.value.getHalfCheckedKeys()
|
||||
const currentPermissions = [...checkedKeys, ...halfCheckedKeys]
|
||||
// 如果正在初始化树,忽略此次check事件
|
||||
if (isInitializingTree.value) return
|
||||
|
||||
// 对比原始权限和当前选中的权限,找出需要新增和移除的权限
|
||||
const addedPermissions = currentPermissions.filter(
|
||||
(id) => !originalPermissions.value.includes(id)
|
||||
)
|
||||
const removedPermissions = originalPermissions.value.filter(
|
||||
(id) => !currentPermissions.includes(id)
|
||||
)
|
||||
// 获取当前勾选的所有节点(不包括半选状态)
|
||||
const checkedKeys = permissionTreeRef.value.getCheckedKeys(false)
|
||||
|
||||
// 使用 Promise.all 并发执行新增和移除操作
|
||||
const promises: Promise<any>[] = []
|
||||
// 找出新增的权限(当前勾选中不在已分配列表中的)
|
||||
const newPermissions = checkedKeys.filter((id) => !selectedPermissions.value.includes(id))
|
||||
|
||||
// 如果有新增的权限,调用分配接口
|
||||
if (addedPermissions.length > 0) {
|
||||
promises.push(RoleService.assignPermissions(currentRoleId.value, addedPermissions))
|
||||
}
|
||||
if (newPermissions.length > 0) {
|
||||
try {
|
||||
// 调用API分配权限
|
||||
await RoleService.assignPermissions(currentRoleId.value, newPermissions)
|
||||
|
||||
// 如果有移除的权限,调用移除接口
|
||||
if (removedPermissions.length > 0) {
|
||||
removedPermissions.forEach((permId) => {
|
||||
promises.push(RoleService.removePermission(currentRoleId.value, permId))
|
||||
// 更新已分配权限列表
|
||||
selectedPermissions.value = [...selectedPermissions.value, ...newPermissions]
|
||||
buildAssignedPermissionsList()
|
||||
|
||||
ElMessage.success('权限添加成功')
|
||||
} catch (error) {
|
||||
console.error('添加权限失败:', error)
|
||||
ElMessage.error('权限添加失败')
|
||||
|
||||
// 如果添加失败,恢复树的选中状态
|
||||
nextTick(() => {
|
||||
permissionTreeRef.value?.setCheckedKeys(selectedPermissions.value, false)
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 重新设置树的选中状态为已分配的权限(阻止取消勾选)
|
||||
nextTick(() => {
|
||||
permissionTreeRef.value?.setCheckedKeys(selectedPermissions.value, false)
|
||||
})
|
||||
}
|
||||
|
||||
// 移除单个权限
|
||||
const removePermission = async (permId: number) => {
|
||||
try {
|
||||
await RoleService.removePermission(currentRoleId.value, permId)
|
||||
|
||||
// 重新从服务器获取最新的权限列表
|
||||
const res = await RoleService.getRolePermissions(currentRoleId.value)
|
||||
|
||||
if (res.code === 0 || Array.isArray(res.data)) {
|
||||
const permissions = res.data || []
|
||||
|
||||
// 清空并重新设置权限列表
|
||||
if (Array.isArray(permissions) && permissions.length > 0) {
|
||||
if (typeof permissions[0] === 'object') {
|
||||
if ('ID' in permissions[0]) {
|
||||
selectedPermissions.value = permissions.map((perm: any) => perm.ID)
|
||||
} else if ('id' in permissions[0]) {
|
||||
selectedPermissions.value = permissions.map((perm: any) => perm.id)
|
||||
}
|
||||
} else {
|
||||
selectedPermissions.value = permissions
|
||||
}
|
||||
} else {
|
||||
selectedPermissions.value = []
|
||||
}
|
||||
|
||||
// 重建已分配权限列表
|
||||
buildAssignedPermissionsList()
|
||||
|
||||
// 更新树的选中状态
|
||||
await nextTick()
|
||||
if (permissionTreeRef.value) {
|
||||
isInitializingTree.value = true
|
||||
permissionTreeRef.value.setCheckedKeys(selectedPermissions.value, false)
|
||||
setTimeout(() => {
|
||||
isInitializingTree.value = false
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
|
||||
// 等待所有操作完成
|
||||
if (promises.length > 0) {
|
||||
await Promise.all(promises)
|
||||
ElMessage.success('权限更新成功')
|
||||
} else {
|
||||
ElMessage.info('权限未发生变化')
|
||||
}
|
||||
|
||||
permissionDialogVisible.value = false
|
||||
ElMessage.success('权限移除成功')
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
permissionSubmitLoading.value = false
|
||||
console.error('移除权限失败:', error)
|
||||
ElMessage.error('权限移除失败')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,14 +699,76 @@
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.permission-tree {
|
||||
:deep(.el-tree-node) {
|
||||
margin: 6px 0;
|
||||
.permission-assignment-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
height: 500px;
|
||||
|
||||
.permission-tree-section,
|
||||
.assigned-permissions-section {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
.section-title {
|
||||
padding: 12px 16px;
|
||||
background: var(--el-fill-color-light);
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__content) {
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
.permission-tree-section {
|
||||
.permission-tree {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
|
||||
:deep(.el-tree-node) {
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__content) {
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.assigned-permissions-section {
|
||||
.assigned-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 12px;
|
||||
|
||||
.assigned-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 12px;
|
||||
margin-bottom: 8px;
|
||||
background: var(--el-fill-color-lighter);
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
background: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
.perm-name {
|
||||
flex: 1;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user