Become a sponsor

说明
前后端权限通过统一的权限节点字符串联动,后端 @permission_required 校验权限,前端 v-perm 指令和 TableAction 的 auth 属性控制按钮显示。
统一格式: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 —— 导入Endpoint 使用 @permission_required 装饰器:
# src/api/v1/endpoints/position.py
@router.post('/add')
@permission_required("sys:position:add")
@check_demo
def add(request: Request, data: PositionForm):
return position_service.add(request, data)校验流程:
1. login_required 从 JWT Token 解析用户 ID
2. permission_required 查询用户角色 → 角色菜单 → 权限节点列表
3. 检查 endpoint 要求的权限节点是否在列表中
4. 用户 ID=1(管理员)跳过检查按钮使用 v-perm 指令(满足任一权限即可显示):
<!-- src/views/system/position/index.vue -->
<el-button type="primary" @click="handleAdd" v-perm="['sys:position:add']">
添加岗位
</el-button>
<el-button type="danger" @click="handleDelete()" :disabled="!selectionData.length"
v-perm="['sys:position:batchDelete']">
删除
</el-button>操作列通过 TableAction 组件的 auth 属性控制:
const actionColumn = {
render(record) {
return h(TableAction, {
style: 'button',
actions: [
{
label: '编辑',
icon: 'Edit',
type: 'warning',
onClick: handleEdit.bind(null, record),
auth: ['sys:position:update'],
},
{
label: '删除',
icon: 'Delete',
type: 'danger',
onClick: handleDelete.bind(null, record),
auth: ['sys:position:delete'],
},
],
});
},
};在逻辑中检查权限:
import { usePermission } from '@/hooks/web/usePermission';
const { hasPermission, hasSomePermission } = usePermission();
// v-if 条件渲染
const showExportBtn = computed(() => hasPermission(['sys:position:export']));权限节点在菜单管理中配置,菜单类型为「按钮」:
菜单管理 → 系统管理 → 岗位管理
├── 岗位查询(sys:position:page)—— 类型:菜单
├── 岗位新增(sys:position:add)—— 类型:按钮
├── 岗位编辑(sys:position:update)—— 类型:按钮
├── 岗位删除(sys:position:delete)—— 类型:按钮
├── 岗位批量删除(sys:position:batchDelete)—— 类型:按钮
└── 岗位状态(sys:position:status)—— 类型:按钮后端菜单表 → adminMenus API → routerGenerator 生成路由表(含 permission 字段)
↓
userStore.GetInfo() → 获取 permissions 列表
↓
v-perm 指令 mounted → hasSomePermission(permissions)
↓
有权限 → 保留元素 / 无权限 → 移除元素前端权限列表在登录后通过 getUserInfo 接口获取,存储在 user store 的 permissions 数组中:
// src/store/modules/user.ts
GetInfo() {
return new Promise((resolve, reject) => {
getUserInfo().then((res) => {
if (res.permissions && res.permissions.length) {
this.setPermissions(res.permissions);
// permissions 示例:["sys:position:page", "sys:position:add", ...]
}
this.setUserInfo(res);
resolve(res);
}).catch(reject);
});
},1. 后端 endpoint 的 permission_required 权限字符串必须与菜单配置的节点一致
2. 前端 v-perm 指令和 TableAction auth 的权限字符串必须与菜单配置的节点一致
3. 权限字符串区分大小写
4. 用户 ID=1(管理员)拥有所有权限(后端跳过检查)
5. 前端权限列表包含 "*:*:*" 通配符时跳过所有检查检查步骤:
1. 确认菜单管理中已配置对应的按钮权限节点
2. 确认角色已分配该菜单权限
3. 确认用户已关联该角色
4. 确认前端 v-perm 字符串与菜单节点完全一致(区分大小写)
5. 确认 userStore.permissions 已正确加载检查步骤:
1. 确认后端 permission_required 字符串与菜单节点一致
2. 确认菜单类型为「按钮」而非「菜单」
3. 确认角色已分配该权限
4. 确认 Token 未过期温馨提示
权限节点的命名建议遵循 sys:{module}:{action} 规范,保持前后端一致。新增模块时,先在菜单管理中配置权限节点,再在后端和前端使用。前端 v-perm 仅做 UI 层隐藏,真正的权限校验在后端。
前后端权限通过统一的权限节点字符串联动。后端 @permission_required 做真正的权限校验(用户 ID=1 跳过),前端 v-perm 指令和 TableAction 的 auth 属性做 UI 层隐藏。权限列表在登录时从后端获取,存储在 user store 中。*:*:* 通配符表示超级管理员。