fetch(modify):修改bug
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m20s

This commit is contained in:
sexygoat
2026-01-31 16:33:21 +08:00
parent 16d53709ef
commit ecb79dae43
20 changed files with 1369 additions and 649 deletions

View File

@@ -312,12 +312,51 @@
}
])
// 将扁平数据转换为树形结构
const buildTreeData = (flatData: Permission[]): Permission[] => {
const map = new Map<number, Permission>()
const result: Permission[] = []
// 先创建所有节点的映射
flatData.forEach((item) => {
map.set(item.ID, { ...item, children: [] })
})
// 构建树形结构
map.forEach((item) => {
if (item.parent_id && map.has(item.parent_id)) {
const parent = map.get(item.parent_id)!
if (!parent.children) {
parent.children = []
}
parent.children.push(item)
} else {
// 没有父节点的是根节点
result.push(item)
}
})
// 递归排序
const sortTree = (nodes: Permission[]): Permission[] => {
return nodes
.sort((a, b) => (a.sort || 0) - (b.sort || 0))
.map((node) => ({
...node,
children: node.children && node.children.length > 0 ? sortTree(node.children) : undefined
}))
}
return sortTree(result)
}
// 获取权限列表
const getPermissionList = async () => {
try {
const response = await PermissionService.getPermissions(searchForm)
if (response.code === 0) {
permissionList.value = response.data.items || []
const flatData = response.data.items || []
// 将扁平数据转换为树形结构
permissionList.value = buildTreeData(flatData)
// 构建权限树选项
buildPermissionTreeOptions()
}
@@ -332,7 +371,7 @@
return list.map((item) => ({
value: item.ID,
label: item.perm_name,
children: item.children ? buildTree(item.children) : undefined
children: item.children && item.children.length > 0 ? buildTree(item.children) : undefined
}))
}
permissionTreeOptions.value = buildTree(permissionList.value)

View File

@@ -89,24 +89,28 @@
<!-- 分配权限对话框 -->
<ElDialog v-model="permissionDialogVisible" title="分配权限" width="500px">
<ElCheckboxGroup v-model="selectedPermissions">
<div
v-for="permission in allPermissions"
:key="permission.ID"
style="margin-bottom: 12px"
>
<ElCheckbox :label="permission.ID">
{{ permission.perm_name }}
<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="permission.perm_type === 1 ? 'info' : 'success'"
:type="data.perm_type === 1 ? 'info' : 'success'"
size="small"
style="margin-left: 8px"
>
{{ permission.perm_type === 1 ? '菜单' : '按钮' }}
{{ data.perm_type === 1 ? '菜单' : '按钮' }}
</ElTag>
</ElCheckbox>
</div>
</ElCheckboxGroup>
</span>
</template>
</ElTree>
<template #footer>
<div class="dialog-footer">
<ElButton @click="permissionDialogVisible = false">取消</ElButton>
@@ -132,30 +136,34 @@
ElMessage,
ElMessageBox,
ElTag,
ElCheckbox,
ElCheckboxGroup,
ElTree,
ElSwitch
} from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import type { PlatformRole, Permission } from '@/types/api'
import type { SearchFormItem } from '@/types'
import { useCheckedColumns } from '@/composables/useCheckedColumns'
import { useAuth } from '@/composables/useAuth'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import { formatDateTime } from '@/utils/business/format'
import { CommonStatus, getStatusText } from '@/config/constants'
defineOptions({ name: 'Role' })
const { hasAuth } = useAuth()
const dialogVisible = ref(false)
const permissionDialogVisible = ref(false)
const loading = ref(false)
const submitLoading = ref(false)
const permissionSubmitLoading = ref(false)
const tableRef = ref()
const permissionTreeRef = ref()
const currentRoleId = ref<number>(0)
const selectedPermissions = ref<number[]>([])
const originalPermissions = ref<number[]>([]) // 保存原始权限,用于对比
const allPermissions = ref<Permission[]>([])
const permissionTreeData = ref<any[]>([])
// 搜索表单初始值
const initialSearchState = {
@@ -272,20 +280,39 @@
width: 200,
fixed: 'right',
formatter: (row: any) => {
return h('div', { style: 'display: flex; gap: 8px;' }, [
h(ArtButtonTable, {
icon: '&#xe72b;',
onClick: () => showPermissionDialog(row)
}),
h(ArtButtonTable, {
type: 'edit',
onClick: () => showDialog('edit', row)
}),
h(ArtButtonTable, {
type: 'delete',
onClick: () => deleteRole(row)
})
])
const buttons = []
// 分配权限按钮
if (hasAuth('role:permission')) {
buttons.push(
h(ArtButtonTable, {
icon: '&#xe72b;',
onClick: () => showPermissionDialog(row)
})
)
}
// 编辑按钮
if (hasAuth('role:edit')) {
buttons.push(
h(ArtButtonTable, {
type: 'edit',
onClick: () => showDialog('edit', row)
})
)
}
// 删除按钮
if (hasAuth('role:delete')) {
buttons.push(
h(ArtButtonTable, {
type: 'delete',
onClick: () => deleteRole(row)
})
)
}
return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
}
}
])
@@ -295,12 +322,59 @@
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 {
// 没有父节点的是根节点
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
}))
}
return sortAndCleanTree(result)
}
// 加载所有权限列表
const loadAllPermissions = async () => {
try {
const res = await PermissionService.getPermissions({ page: 1, page_size: 1000 })
if (res.code === 0) {
allPermissions.value = res.data.items || []
// 构建树形数据
permissionTreeData.value = buildTreeData(allPermissions.value)
}
} catch (error) {
console.error('获取权限列表失败:', error)
@@ -343,14 +417,21 @@
// 提交分配权限
const handleAssignPermissions = async () => {
if (!permissionTreeRef.value) return
permissionSubmitLoading.value = true
try {
// 获取选中的节点(包括半选中的父节点)
const checkedKeys = permissionTreeRef.value.getCheckedKeys()
const halfCheckedKeys = permissionTreeRef.value.getHalfCheckedKeys()
const currentPermissions = [...checkedKeys, ...halfCheckedKeys]
// 对比原始权限和当前选中的权限,找出需要新增和移除的权限
const addedPermissions = selectedPermissions.value.filter(
const addedPermissions = currentPermissions.filter(
(id) => !originalPermissions.value.includes(id)
)
const removedPermissions = originalPermissions.value.filter(
(id) => !selectedPermissions.value.includes(id)
(id) => !currentPermissions.includes(id)
)
// 使用 Promise.all 并发执行新增和移除操作
@@ -532,3 +613,16 @@
}
}
</script>
<style scoped lang="scss">
.permission-tree {
:deep(.el-tree-node) {
margin: 6px 0;
}
:deep(.el-tree-node__content) {
height: 36px;
line-height: 36px;
}
}
</style>