PERMISSION_GUIDE.md 5.0 KB

JeecgBoot 权限接入指南

概述

本项目已集成 JeecgBoot 后台权限系统,支持动态菜单渲染和细粒度的权限控制。

目录结构

src/
├── contexts/
│   └── AuthContext.tsx          # 权限上下文,管理菜单和权限数据
├── hooks/
│   └── usePermission.ts         # 权限检查 Hook
├── services/
│   └── api.ts                   # API 请求封装
├── types/
│   └── menu.ts                  # 类型定义
├── components/
│   └── common/
│       ├── PermissionButton.tsx    # 权限按钮组件
│       └── PermissionWrapper.tsx   # 权限包装组件
└── examples/
    └── PermissionUsage.tsx      # 使用示例

快速开始

1. 配置环境变量

复制 .env.example.env,配置后端 API 地址:

VITE_API_BASE_URL=http://localhost:8080

2. 在应用中使用 AuthProvider

import { AuthProvider } from "./contexts/AuthContext";

function App() {
  return (
    <AuthProvider>
      {/* 你的应用组件 */}
    </AuthProvider>
  );
}

3. 使用权限控制

方式一:使用 PermissionButton 组件

import PermissionButton from "@/components/common/PermissionButton";

<PermissionButton menuId="user-management" action="add" variant="primary">
  新增用户
</PermissionButton>

方式二:使用 PermissionWrapper 组件

import PermissionWrapper from "@/components/common/PermissionWrapper";

<PermissionWrapper menuId="user-management" action="delete">
  <Button variant="negative">删除</Button>
</PermissionWrapper>

方式三:使用 usePermission Hook

import { usePermission } from "@/hooks/usePermission";

function MyComponent() {
  const permission = usePermission("user-management");

  return (
    <>
      {permission.canAdd && <Button>新增</Button>}
      {permission.canEdit && <Button>编辑</Button>}
      {permission.canDelete && <Button>删除</Button>}
    </>
  );
}

权限类型

系统支持以下标准权限类型:

  • view - 查看权限
  • add - 新增权限
  • edit - 编辑权限
  • delete - 删除权限
  • export - 导出权限
  • import - 导入权限

你也可以使用自定义权限标识:

permission.hasAction("custom-action")

API 接口

获取用户菜单

GET /sys/permission/getUserPermissionByToken

返回格式:

[
  {
    "id": "menu-1",
    "name": "user-management",
    "path": "/user",
    "meta": {
      "title": "用户管理",
      "icon": "user"
    },
    "children": []
  }
]

获取用户权限

GET /sys/permission/getPermissionRuleByUser

返回格式:

[
  {
    "id": "perm-1",
    "menuId": "menu-1",
    "actions": ["view", "add", "edit", "delete"]
  }
]

最佳实践

1. 菜单 ID 管理

建议在配置文件中统一管理菜单 ID:

// src/config/menuIds.ts
export const MENU_IDS = {
  USER_MANAGEMENT: "user-management",
  ROLE_MANAGEMENT: "role-management",
  CONTENT_MANAGEMENT: "content-management",
} as const;

使用时:

import { MENU_IDS } from "@/config/menuIds";

<PermissionButton menuId={MENU_IDS.USER_MANAGEMENT} action="add">
  新增用户
</PermissionButton>

2. 路由级权限控制

import { Navigate } from "react-router-dom";
import { usePermission } from "@/hooks/usePermission";

function ProtectedRoute({ menuId, children }) {
  const { canView } = usePermission(menuId);

  if (!canView) {
    return <Navigate to="/403" />;
  }

  return children;
}

3. 表格操作列权限控制

function TableActions({ record, menuId }) {
  const permission = usePermission(menuId);

  return (
    <>
      {permission.canEdit && (
        <Button onClick={() => handleEdit(record)}>编辑</Button>
      )}
      {permission.canDelete && (
        <Button onClick={() => handleDelete(record)}>删除</Button>
      )}
    </>
  );
}

注意事项

  1. Token 管理:确保在登录后将 token 存储到 localStorage
  2. 错误处理:API 请求失败时会抛出异常,建议添加全局错误处理
  3. 权限刷新:用户权限变更后,调用 refreshAuth() 刷新权限数据
  4. 性能优化:权限数据使用 Map 存储,查询性能为 O(1)

故障排查

菜单不显示

  1. 检查 API 地址是否正确
  2. 检查 token 是否有效
  3. 检查后端返回的菜单数据格式

权限按钮不显示

  1. 确认 menuId 是否正确
  2. 确认后端返回的权限数据中包含对应的 action
  3. 检查浏览器控制台是否有错误信息

扩展

自定义权限检查逻辑

如果需要更复杂的权限检查逻辑,可以扩展 hasPermission 函数:

// src/contexts/AuthContext.tsx
const hasPermission = (menuId: string, action: string): boolean => {
  // 超级管理员拥有所有权限
  if (userRole === "admin") {
    return true;
  }

  const actions = permissions.get(menuId);
  return actions ? actions.includes(action) : false;
};