mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-09 20:57:17 +08:00
feat(system/role): 新增查询角色权限树列表接口(替换角色分配权限的菜单树列表接口)
This commit is contained in:
@@ -31,6 +31,11 @@ export function deleteRole(id: string) {
|
|||||||
return http.del(`${BASE_URL}`, { ids: [id] })
|
return http.del(`${BASE_URL}`, { ids: [id] })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @desc 查询角色权限树 */
|
||||||
|
export function listRolePermissionTree() {
|
||||||
|
return http.get<T.RolePermissionResp[]>(`${BASE_URL}/permission/tree`)
|
||||||
|
}
|
||||||
|
|
||||||
/** @desc 修改角色权限 */
|
/** @desc 修改角色权限 */
|
||||||
export function updateRolePermission(id: string, data: any) {
|
export function updateRolePermission(id: string, data: any) {
|
||||||
return http.put(`${BASE_URL}/${id}/permission`, data)
|
return http.put(`${BASE_URL}/${id}/permission`, data)
|
||||||
|
@@ -63,6 +63,15 @@ export type RoleDetailResp = RoleResp & {
|
|||||||
menuCheckStrictly: boolean
|
menuCheckStrictly: boolean
|
||||||
deptCheckStrictly: boolean
|
deptCheckStrictly: boolean
|
||||||
}
|
}
|
||||||
|
export interface RolePermissionResp {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
parentId: string
|
||||||
|
permission?: string
|
||||||
|
children?: RolePermissionResp[]
|
||||||
|
permissions?: RolePermissionResp[]
|
||||||
|
isChecked?: boolean
|
||||||
|
}
|
||||||
export interface RoleUserResp {
|
export interface RoleUserResp {
|
||||||
id: string
|
id: string
|
||||||
username: string
|
username: string
|
||||||
|
@@ -96,7 +96,7 @@
|
|||||||
import type { TableInstance } from '@arco-design/web-vue'
|
import type { TableInstance } from '@arco-design/web-vue'
|
||||||
import { Message, Modal } from '@arco-design/web-vue'
|
import { Message, Modal } from '@arco-design/web-vue'
|
||||||
import MenuAddModal from './MenuAddModal.vue'
|
import MenuAddModal from './MenuAddModal.vue'
|
||||||
import { type MenuQuery, type MenuResp, clearMenuCache, deleteMenu, listMenu } from '@/apis/system/menu'
|
import { type MenuQuery, type MenuResp, clearMenuCache, deleteMenu, listMenuDictTree } from '@/apis/system/menu'
|
||||||
import type GiTable from '@/components/GiTable/index.vue'
|
import type GiTable from '@/components/GiTable/index.vue'
|
||||||
import { useTable } from '@/hooks'
|
import { useTable } from '@/hooks'
|
||||||
import { isMobile } from '@/utils'
|
import { isMobile } from '@/utils'
|
||||||
@@ -111,7 +111,7 @@ const {
|
|||||||
loading,
|
loading,
|
||||||
search,
|
search,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
} = useTable(() => listMenu(queryForm), { immediate: true })
|
} = useTable(() => listMenuDictTree({ description: queryForm.description || '' }), { immediate: true })
|
||||||
|
|
||||||
// 过滤树
|
// 过滤树
|
||||||
const searchData = (title: string, path: string, permission: string) => {
|
const searchData = (title: string, path: string, permission: string) => {
|
||||||
|
@@ -56,12 +56,11 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { nextTick, ref, watch } from 'vue'
|
import { nextTick, ref, watch } from 'vue'
|
||||||
import { Message, type TableInstance } from '@arco-design/web-vue'
|
import { Message, type TableInstance, type TreeNodeData } from '@arco-design/web-vue'
|
||||||
import { type MenuResp, listMenu } from '@/apis/system/menu'
|
|
||||||
import { isMobile } from '@/utils'
|
import { isMobile } from '@/utils'
|
||||||
import type GiTable from '@/components/GiTable/index.vue'
|
import type GiTable from '@/components/GiTable/index.vue'
|
||||||
import { useTable } from '@/hooks'
|
import { useTable } from '@/hooks'
|
||||||
import { getRole, updateRolePermission } from '@/apis'
|
import { type RolePermissionResp, getRole, listRolePermissionTree, updateRolePermission } from '@/apis/system/role'
|
||||||
import has from '@/utils/has'
|
import has from '@/utils/has'
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
@@ -72,16 +71,7 @@ interface Props {
|
|||||||
roleId: string
|
roleId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PermissionItem {
|
interface ExtendedRolePermissionResp extends RolePermissionResp {
|
||||||
id: string | number
|
|
||||||
title: string
|
|
||||||
parentId: string | number
|
|
||||||
permission?: string
|
|
||||||
isChecked?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ExtendedMenuResp extends MenuResp {
|
|
||||||
permissions?: PermissionItem[]
|
|
||||||
checkedPermissions?: (string | number)[]
|
checkedPermissions?: (string | number)[]
|
||||||
isChecked?: boolean
|
isChecked?: boolean
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
@@ -105,12 +95,12 @@ const onExpanded = () => {
|
|||||||
*
|
*
|
||||||
* @param menus 菜单数据
|
* @param menus 菜单数据
|
||||||
*/
|
*/
|
||||||
const transformMenu = (menus: MenuResp[]): ExtendedMenuResp[] => {
|
const transformMenu = (menus: RolePermissionResp[]): ExtendedRolePermissionResp[] => {
|
||||||
return menus.map((item): ExtendedMenuResp => {
|
return menus.map((item): ExtendedRolePermissionResp => {
|
||||||
// 如果当前项有子项,递归处理子项
|
// 如果当前项有子项,递归处理子项
|
||||||
if (item.children && item.children.length > 0) {
|
if (item.children && item.children.length > 0) {
|
||||||
// 过滤出 type 为 3 的按钮权限
|
// 过滤出 permission 不为空的子项
|
||||||
const permissions = item.children.filter((child) => child.type === 3 || child.permission).map((child): PermissionItem => ({
|
const permissions = item.children.filter((child) => child.permission).map((child): RolePermissionResp => ({
|
||||||
id: child.id,
|
id: child.id,
|
||||||
title: child.title,
|
title: child.title,
|
||||||
parentId: child.parentId,
|
parentId: child.parentId,
|
||||||
@@ -118,13 +108,13 @@ const transformMenu = (menus: MenuResp[]): ExtendedMenuResp[] => {
|
|||||||
isChecked: false,
|
isChecked: false,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// 过滤出 type 不为 3 的子项
|
// 过滤出 permission 为空的子项
|
||||||
item.children = item.children.filter((child) => child.type !== 3 && !child.permission)
|
item.children = item.children.filter((child) => !child.permission)
|
||||||
|
|
||||||
// 如果有权限,将其添加到当前项的 permissions 属性中
|
// 如果有权限,将其添加到当前项的 permissions 属性中
|
||||||
if (permissions.length > 0) {
|
if (permissions.length > 0) {
|
||||||
(item as ExtendedMenuResp).permissions = permissions
|
(item as ExtendedRolePermissionResp).permissions = permissions
|
||||||
;(item as ExtendedMenuResp).checkedPermissions = permissions.filter((permission) => permission.isChecked).map((permission) => permission.id)
|
;(item as ExtendedRolePermissionResp).checkedPermissions = permissions.filter((permission) => permission.isChecked).map((permission) => permission.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归处理剩余的子项
|
// 递归处理剩余的子项
|
||||||
@@ -141,7 +131,7 @@ const transformMenu = (menus: MenuResp[]): ExtendedMenuResp[] => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新表格数据的选中状态
|
// 更新表格数据的选中状态
|
||||||
const updateTableDataCheckedStatus = (data: ExtendedMenuResp[], selectedKeys: (string | number)[]) => {
|
const updateTableDataCheckedStatus = (data: ExtendedRolePermissionResp[], selectedKeys: (string | number)[]) => {
|
||||||
data.forEach((item) => {
|
data.forEach((item) => {
|
||||||
item.disabled = disabled.value
|
item.disabled = disabled.value
|
||||||
// 设置菜单项的选中状态
|
// 设置菜单项的选中状态
|
||||||
@@ -157,23 +147,23 @@ const updateTableDataCheckedStatus = (data: ExtendedMenuResp[], selectedKeys: (s
|
|||||||
}
|
}
|
||||||
// 递归处理子菜单
|
// 递归处理子菜单
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
updateTableDataCheckedStatus(item.children as ExtendedMenuResp[], selectedKeys)
|
updateTableDataCheckedStatus(item.children as ExtendedRolePermissionResp[], selectedKeys)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查找指定菜单 - 使用 Map 缓存优化查找性能
|
// 查找指定菜单 - 使用 Map 缓存优化查找性能
|
||||||
const menuMap = ref<Map<string | number, ExtendedMenuResp>>(new Map())
|
const menuMap = ref<Map<string | number, ExtendedRolePermissionResp>>(new Map())
|
||||||
|
|
||||||
// 构建菜单映射缓存
|
// 构建菜单映射缓存
|
||||||
const buildMenuMap = (data: ExtendedMenuResp[]) => {
|
const buildMenuMap = (data: ExtendedRolePermissionResp[]) => {
|
||||||
const map = new Map<string | number, ExtendedMenuResp>()
|
const map = new Map<string | number, ExtendedRolePermissionResp>()
|
||||||
|
|
||||||
const traverse = (items: ExtendedMenuResp[]) => {
|
const traverse = (items: ExtendedRolePermissionResp[]) => {
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
map.set(item.id, item)
|
map.set(item.id, item)
|
||||||
if (item.children?.length) {
|
if (item.children?.length) {
|
||||||
traverse(item.children as ExtendedMenuResp[])
|
traverse(item.children as ExtendedRolePermissionResp[])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -188,9 +178,9 @@ const {
|
|||||||
tableData,
|
tableData,
|
||||||
loading,
|
loading,
|
||||||
search,
|
search,
|
||||||
} = useTable(() => listMenu(), {
|
} = useTable(() => listRolePermissionTree(), {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
formatResult(data: MenuResp[]) {
|
formatResult(data: TreeNodeData[]) {
|
||||||
return transformMenu(data)
|
return transformMenu(data)
|
||||||
},
|
},
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
@@ -198,10 +188,10 @@ const {
|
|||||||
tableRef.value?.tableRef?.expandAll(true)
|
tableRef.value?.tableRef?.expandAll(true)
|
||||||
})
|
})
|
||||||
// 构建菜单映射缓存
|
// 构建菜单映射缓存
|
||||||
buildMenuMap(tableData.value as ExtendedMenuResp[])
|
buildMenuMap(tableData.value as ExtendedRolePermissionResp[])
|
||||||
// 初始加载时应用已选中的权限
|
// 初始加载时应用已选中的权限
|
||||||
if (selectedKeys.value.size > 0) {
|
if (selectedKeys.value.size > 0) {
|
||||||
updateTableDataCheckedStatus(tableData.value as ExtendedMenuResp[], Array.from(selectedKeys.value))
|
updateTableDataCheckedStatus(tableData.value as ExtendedRolePermissionResp[], Array.from(selectedKeys.value))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -212,13 +202,13 @@ const columns: TableInstance['columns'] = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
// 级联选中子项
|
// 级联选中子项
|
||||||
const cascadeSelectChild = (record: ExtendedMenuResp, isCascade: boolean) => {
|
const cascadeSelectChild = (record: ExtendedRolePermissionResp, isCascade: boolean) => {
|
||||||
if (!isCascade) return
|
if (!isCascade) return
|
||||||
|
|
||||||
// 批量处理子菜单
|
// 批量处理子菜单
|
||||||
if (record.children && record.children.length > 0) {
|
if (record.children && record.children.length > 0) {
|
||||||
record.children.forEach((child) => {
|
record.children.forEach((child) => {
|
||||||
const extendedChild = child as ExtendedMenuResp
|
const extendedChild = child as ExtendedRolePermissionResp
|
||||||
extendedChild.isChecked = record.isChecked
|
extendedChild.isChecked = record.isChecked
|
||||||
tableRef.value?.tableRef?.select(child.id, extendedChild.isChecked)
|
tableRef.value?.tableRef?.select(child.id, extendedChild.isChecked)
|
||||||
|
|
||||||
@@ -253,19 +243,19 @@ const cascadeSelectChild = (record: ExtendedMenuResp, isCascade: boolean) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 查找指定菜单
|
// 查找指定菜单
|
||||||
const findItem = (id: string | number): ExtendedMenuResp | null => {
|
const findItem = (id: string | number): ExtendedRolePermissionResp | null => {
|
||||||
return menuMap.value.get(id) || null
|
return menuMap.value.get(id) || null
|
||||||
}
|
}
|
||||||
|
|
||||||
// 级联选中父项目
|
// 级联选中父项目
|
||||||
const cascadeSelectParent = (record: ExtendedMenuResp, isCascade: boolean) => {
|
const cascadeSelectParent = (record: ExtendedRolePermissionResp, isCascade: boolean) => {
|
||||||
if (!isCascade || !record.parentId || record.parentId === '0') return
|
if (!isCascade || !record.parentId || record.parentId === '0') return
|
||||||
|
|
||||||
const parent = findItem(record.parentId)
|
const parent = findItem(record.parentId)
|
||||||
if (!parent) return
|
if (!parent) return
|
||||||
|
|
||||||
// 检查父项目的所有子项是否有被选中的
|
// 检查父项目的所有子项是否有被选中的
|
||||||
const hasCheckedChildren = parent.children?.some((child) => (child as ExtendedMenuResp).isChecked)
|
const hasCheckedChildren = parent.children?.some((child) => (child as ExtendedRolePermissionResp).isChecked)
|
||||||
parent.isChecked = hasCheckedChildren || false
|
parent.isChecked = hasCheckedChildren || false
|
||||||
|
|
||||||
// 更新表格选中状态
|
// 更新表格选中状态
|
||||||
@@ -286,7 +276,7 @@ const cascadeSelectParent = (record: ExtendedMenuResp, isCascade: boolean) => {
|
|||||||
|
|
||||||
// 选中
|
// 选中
|
||||||
const select: TableInstance['onSelect'] = (rowKeys, checked, record) => {
|
const select: TableInstance['onSelect'] = (rowKeys, checked, record) => {
|
||||||
const extendedRecord = record as ExtendedMenuResp
|
const extendedRecord = record as ExtendedRolePermissionResp
|
||||||
|
|
||||||
// 如果处于禁用状态,直接返回,不执行任何逻辑
|
// 如果处于禁用状态,直接返回,不执行任何逻辑
|
||||||
if (disabled.value || extendedRecord.disabled) {
|
if (disabled.value || extendedRecord.disabled) {
|
||||||
@@ -312,7 +302,7 @@ const selectAll: TableInstance['onSelectAll'] = (checked) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tableData.value.forEach((item) => {
|
tableData.value.forEach((item) => {
|
||||||
const extendedItem = item as ExtendedMenuResp
|
const extendedItem = item as ExtendedRolePermissionResp
|
||||||
extendedItem.isChecked = checked
|
extendedItem.isChecked = checked
|
||||||
checked
|
checked
|
||||||
? selectedKeys.value.add(item.id)
|
? selectedKeys.value.add(item.id)
|
||||||
@@ -322,7 +312,7 @@ const selectAll: TableInstance['onSelectAll'] = (checked) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 选中权限
|
// 选中权限
|
||||||
const selectPermission = (record: ExtendedMenuResp) => {
|
const selectPermission = (record: ExtendedRolePermissionResp) => {
|
||||||
// 如果处于禁用状态,直接返回,不执行任何逻辑
|
// 如果处于禁用状态,直接返回,不执行任何逻辑
|
||||||
if (disabled.value || record.disabled) {
|
if (disabled.value || record.disabled) {
|
||||||
return
|
return
|
||||||
@@ -384,9 +374,9 @@ const fetchRole = async (id: string) => {
|
|||||||
// 更新选中键集合
|
// 更新选中键集合
|
||||||
selectedKeys.value = new Set(data.menuIds)
|
selectedKeys.value = new Set(data.menuIds)
|
||||||
// 重新构建菜单映射缓存
|
// 重新构建菜单映射缓存
|
||||||
buildMenuMap(tableData.value as ExtendedMenuResp[])
|
buildMenuMap(tableData.value as ExtendedRolePermissionResp[])
|
||||||
// 更新表格数据的选中状态
|
// 更新表格数据的选中状态
|
||||||
updateTableDataCheckedStatus(tableData.value as ExtendedMenuResp[], data.menuIds)
|
updateTableDataCheckedStatus(tableData.value as ExtendedRolePermissionResp[], data.menuIds)
|
||||||
// 手动设置表格行的选中状态,确保组件响应
|
// 手动设置表格行的选中状态,确保组件响应
|
||||||
await nextTick(() => {
|
await nextTick(() => {
|
||||||
tableRef.value?.tableRef?.selectAll(false)
|
tableRef.value?.tableRef?.selectAll(false)
|
||||||
|
Reference in New Issue
Block a user