# 权限指令 v-perm :::tip 说明 `v-perm` 和 `v-perms` 是项目自定义的 Vue 指令,用于按钮级别的权限控制,无权限时自动从 DOM 中移除元素。底层通过 `usePermission` Hook 检查用户权限列表。 ::: ## 指令定义 权限指令定义在 `src/directives/permission.ts` 中: ```typescript // src/directives/permission.ts import { ObjectDirective } from 'vue'; import { usePermission } from '@/hooks/web/usePermission'; // v-perm:满足任一权限即可显示 export const perm: ObjectDirective = { mounted(el: HTMLButtonElement, binding) { if (binding.value == undefined) return; const { hasSomePermission } = usePermission(); if (!hasSomePermission(binding.value)) { el.parentNode.removeChild(el); } }, }; // v-perms:必须满足所有权限才显示 export const perms: ObjectDirective = { mounted(el: HTMLButtonElement, binding) { if (binding.value == undefined) return; const { hasEveryPermission } = usePermission(); if (!hasEveryPermission(binding.value)) { el.parentNode.removeChild(el); } }, }; ``` 指令在 `mounted` 钩子中检查当前用户的权限列表,如果不满足权限条件,直接从 DOM 中移除元素。 ## usePermission Hook 权限检查的核心逻辑在 `src/hooks/web/usePermission.ts` 中: ```typescript // src/hooks/web/usePermission.ts import { useUserStore } from '@/store/modules/user'; export function usePermission() { const userStore = useUserStore(); function _somePermissions(accesses: string[]) { const permissionsList = userStore.getPermissions; if (permissionsList[0] == '*:*:*') return true; // 超级管理员通配符 return accesses.some((item) => permissionsList.includes(item)); } // 是否包含其中某个权限 function hasSomePermission(accesses?: string | string[]): boolean { const permissionsList = userStore.getPermissions; if (permissionsList[0] === '*:*:*') return true; const list = Array.isArray(accesses) ? accesses : []; return list.some((access) => permissionsList.includes(access)); } // 是否包含指定的所有权限 function hasEveryPermission(accesses?: string | string[]): boolean { const list = Array.isArray(accesses) ? accesses : []; const permissionsList = userStore.getPermissions; if (permissionsList[0] === '*:*:*') return true; return list.every((access) => permissionsList.includes(access)); } // 判断是否存在权限(可用于 v-if) function hasPermission(accesses: string[]): boolean { if (!accesses || !accesses.length) return true; return _somePermissions(accesses); } return { hasPermission, hasEveryPermission, hasSomePermission }; } ``` 权限列表在登录后通过 `userStore.GetInfo()` 从后端获取,存储在 Pinia 的 user store 中。 ## 基本用法 ### v-perm(满足任一权限) ```vue 添加岗位 删除 导出 ``` ### v-perms(满足所有权限) ```vue 高级操作 ``` ### 与 v-if 结合 ```typescript import { usePermission } from '@/hooks/web/usePermission'; const { hasPermission } = usePermission(); // 在模板中使用 const showAddBtn = computed(() => hasPermission(['sys:position:add'])); ``` ```vue 添加岗位 ``` ## 实际用法(position 模块) 以岗位管理页面为例,实际代码如下: ```vue ``` 操作列中的权限控制通过 `auth` 属性实现: ```typescript const actionColumn = reactive({ width: 200, title: '操作', align: 'center', key: 'action', fixed: 'right', render(record) { return h(TableAction as any, { style: 'button', actions: [ { label: '编辑', icon: renderIcon(FormOutlined), type: 'info', onClick: handleEdit.bind(null, record), auth: ['sys:position:update'], // 权限节点 }, { label: '删除', icon: renderIcon(DeleteOutlined), type: 'error', onClick: handleDelete.bind(null, record), auth: ['sys:position:delete'], // 权限节点 }, ], }); }, }); ``` ## 权限节点命名规范 权限节点格式:`sys:{module}:{action}` ``` sys:position:page —— 分页查询 sys:position:detail —— 查询详情 sys:position:list —— 获取列表 sys:position:add —— 新增 sys:position:update —— 编辑 sys:position:delete —— 删除 sys:position:batchDelete —— 批量删除 sys:position:status —— 设置状态 sys:position:export —— 导出 sys:position:import —— 导入 ``` ## 与后端对应 前端 `v-perm` 指令的权限节点必须与后端 `@permission_required` 装饰器的权限字符串一致: ```python # 后端 @router.post('/add') @permission_required("sys:position:add") @check_demo def add(request: Request, data: PositionForm): return position_service.add(request, data) ``` ```vue 添加岗位 ``` ## 超级管理员 用户权限列表中包含 `*:*:*` 通配符时,所有权限检查直接返回 `true`,等同于后端用户 ID=1 的管理员跳过权限检查。 :::tip 温馨提示 `v-perm` 指令仅做 UI 层隐藏,真正的权限校验在后端 `@permission_required` 装饰器中。即使前端绕过指令限制直接调用接口,后端仍会校验权限。 ::: ## 指令注册 指令在 `src/plugins/` 中通过 `setupDirectives` 全局注册: ```typescript // 启动时注册(main.ts) setupDirectives(app); // 注册 v-perm、v-perms 等指令 ``` ## 总结 `v-perm`(满足任一权限)和 `v-perms`(满足所有权限)指令通过 `usePermission` Hook 检查用户权限列表,无权限时自动从 DOM 移除元素。操作列通过 `TableAction` 组件的 `auth` 属性控制。权限节点在菜单管理中配置,需要保持前后端字符串完全一致。`*:*:*` 通配符表示超级管理员。