角色管理页面接口完成

This commit is contained in:
2026-08-27 09:52:44 +08:00
parent f5176ada20
commit d4be566459
2 changed files with 192 additions and 104 deletions
+98 -10
View File
@@ -4,7 +4,7 @@ import { useAppStore } from '@/store/modules/app';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { useRouter } from 'vue-router';
import { NButton } from 'naive-ui';
import { NButton, NIcon } from 'naive-ui';
import { roleListApi, editRoleApi } from '@/service/api/role';
const router = useRouter();
@@ -12,6 +12,9 @@ const appStore = useAppStore();
const themeStore = useThemeStore();
const gap = computed(() => (appStore.isMobile ? 0 : 16));
const routeTree = ref<any[]>([]);
const allPaths = ref<string[]>([]);
const defaultCheckedKeys = ref<string[]>([]);
const loading = ref<boolean>(false);
const btnLoading = ref<boolean>(false);
const formRef = ref<any>(null);
@@ -94,6 +97,12 @@ const getList = async () => {
// 设置权限
const handleSetPermission = (row: any) => {
currentRole.value = JSON.parse(JSON.stringify(row));
// 所有权限
if(currentRole.value?.perms.length===1 && currentRole.value?.perms[0] === '*'){
defaultCheckedKeys.value = allPaths.value;
}else{
defaultCheckedKeys.value = currentRole.value?.perms || [];
}
permissionModal.value = true;
}
// 编辑角色
@@ -125,15 +134,82 @@ const saveRole = (e: MouseEvent) => {
// 保存权限
const savePermission = async () => {
btnLoading.value = true;
setTimeout(() => {
currentRole.value.perms = defaultCheckedKeys.value;
try {
await editRoleApi(currentRole.value);
window.$message?.success('操作成功')
btnLoading.value = false;
permissionModal.value = false;
}, 1000)
getList();
} finally {
btnLoading.value = false;
}
}
// 更新选中权限
const updateCheckedKeys = (keys: string[]) => {
defaultCheckedKeys.value = keys;
}
// 复制title到顶层
const copyTitleToTop = (node:any) => {
// 创建新节点,复制原节点所有属性
const newNode = { ...node }
// 如果存在 meta.title,则复制到顶层
if (node.meta?.title) {
newNode.title = node.meta.title
} else {
// 可选:没有 title 时用 name 代替
newNode.title = node.name || ''
}
// 如果有 children,递归处理每个子节点
if (Array.isArray(newNode.children) && newNode.children.length > 0) {
newNode.children = newNode.children.map((child:any) => copyTitleToTop(child))
}
return newNode
}
// 获取所有路由路径
const getAllPaths = (tree:any) => {
let paths:string[] = []
tree.forEach((node:any) => {
if (node.path) paths.push(node.path)
if (Array.isArray(node.children) && node.children.length) {
paths = paths.concat(getAllPaths(node.children))
}
})
return paths
}
// 获取所有路由
const getAllRoutes = () => {
const filtered = router.getRoutes().filter((item:any) => {
// 条件1:有name且非常量
if (item.name === undefined || item.meta?.constant === true) return false;
// 条件2path中斜杠数量 < 2(即只有一级)
const path = item.path || '';
const slashCount = (path.match(/\//g) || []).length;
if (slashCount >= 2) return false;
return true;
})
const tree = filtered.map((item:any) => copyTitleToTop(item));
routeTree.value = tree;
allPaths.value = getAllPaths(tree);
}
// tree自定义渲染图标
const renderIcon = (node:any) => {
// 如果节点没有 children 或 children 为空数组,则不显示图标
if (!node.option.children || node.option.children.length === 0) {
return null; // 返回 null 表示不渲染任何图标
}
// 有子节点:返回 undefined 表示使用默认展开图标,也可自定义
return h(Icon,{
icon: node.option.expanded ? 'bi:caret-down-fill' : 'bi:caret-right-fill',
class: 'size-12px',
});
};
onMounted(() => {
const allRoutes = router.getRoutes();
getAllRoutes();
getList()
})
</script>
@@ -192,12 +268,24 @@ onMounted(() => {
<!-- 设置权限抽屉 -->
<NDrawer v-model:show="permissionModal" :width="502" placement="right">
<NDrawerContent :title="`设置权限-${currentRole.name}`" closable>
<template #footer>
<div class="flex justify-end gap-[10px]">
<NButton @click="permissionModal = false">取消</NButton>
<NButton type="primary" :loading="btnLoading" @click="savePermission">保存</NButton>
</div>
</template>
<NTree
block-line
cascade
checkable
key-field="path"
label-field="title"
:selectable="false"
:data="routeTree"
:default-checked-keys="defaultCheckedKeys"
@update:checked-keys="updateCheckedKeys"
:render-switcher-icon="renderIcon"
/>
<template #footer>
<div class="flex justify-end gap-[10px]">
<NButton @click="permissionModal = false">取消</NButton>
<NButton type="primary" :loading="btnLoading" @click="savePermission">保存</NButton>
</div>
</template>
</NDrawerContent>
</NDrawer>
</NCard>