AntDesignPro权限按钮实战指南

Ant Design Pro 权限按钮系统 (TypeScript 实现)

Ant Design Pro 提供了完整的权限管理解决方案。下面是基于 TypeScript 的权限按钮实现方案,结合了 @umijs/plugin-access 插件和自定义组件。

完整实现方案

import React from 'react';
import { useModel, useAccess, Access } from 'umi';
import { Button, Card, Space, PageHeader, Tabs, Typography, message, Popconfirm } from 'antd';
import type { ProColumns } from '@ant-design/pro-table';
import ProTable from '@ant-design/pro-table';
import { PlusOutlined, EditOutlined, DeleteOutlined, DownloadOutlined } from '@ant-design/icons';

const { TabPane } = Tabs;
const { Title } = Typography;

// 用户数据类型
interface User {
  id: string;
  name: string;
  role: string;
  department: string;
}

// 权限模型类型
export type AccessType = 'canView' | 'canCreate' | 'canEdit' | 'canDelete' | 'canExport';

// 产品数据类型
interface Product {
  id: string;
  name: string;
  category: string;
  price: number;
  stock: number;
  createdAt: string;
  status: 'active' | 'inactive';
}

// 权限按钮组件
interface AuthButtonProps {
  accessKey: AccessType;
  title?: string;
  icon?: React.ReactNode;
  type?: 'primary' | 'dashed' | 'link' | 'text' | 'default';
  danger?: boolean;
  ghost?: boolean;
  shape?: 'circle' | 'round';
  size?: 'large' | 'middle' | 'small';
  onClick?: () => void;
  style?: React.CSSProperties;
  confirmText?: string;
  disabled?: boolean;
  children?: React.ReactNode;
}

const AuthButton: React.FC = (props) => {
  const access = useAccess();
  const hasAccess = access[props.accessKey];
  
  // 如果设置了确认框
  if (props.confirmText) {
    return hasAccess ? (
      
        
      
    ) : null;
  }
  
  return hasAccess ? (
    
  ) : null;
};

// 产品列表页面
const ProductPage: React.FC = () => {
  // 获取全局状态中的用户信息
  const { initialState } = useModel('@@initialState');
  const currentUser = initialState?.currentUser as User | undefined;
  
  // 权限管理
  const access = useAccess();
  
  // 模拟产品数据
  const mockProducts: Product[] = [
    { id: '1', name: 'MacBook Pro', category: 'Laptop', price: 1999, stock: 15, createdAt: '2023-01-15', status: 'active' },
    { id: '2', name: 'iPhone 15', category: 'Phone', price: 999, stock: 30, createdAt: '2023-02-20', status: 'active' },
    { id: '3', name: 'iPad Pro', category: 'Tablet', price: 799, stock: 10, createdAt: '2023-03-05', status: 'inactive' },
  ];
  
  // 列定义
  const columns: ProColumns[] = [
    {
      title: '产品名称',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: '类别',
      dataIndex: 'category',
      key: 'category',
    },
    {
      title: '价格($)',
      dataIndex: 'price',
      key: 'price',
      valueType: 'money',
    },
    {
      title: '库存',
      dataIndex: 'stock',
      key: 'stock',
    },
    {
      title: '状态',
      dataIndex: 'status',
      key: 'status',
      valueEnum: {
        active: { text: '激活', status: 'Success' },
        inactive: { text: '未激活', status: 'Default' },
      },
    },
    {
      title: '操作',
      key: 'action',
      render: (text, record) => (
        
          } 
            onClick={() => handleEdit(record)}
          />
          } 
            danger 
            confirmText="确定要删除此产品吗?"
            onClick={() => handleDelete(record)}
          />
        
      ),
    },
  ];
  
  // 操作处理函数
  const handleCreate = () => {
    message.success('打开创建产品模态框');
  };
  
  const handleEdit = (product: Product) => {
    message.info(`编辑产品: ${product.name}`);
  };
  
  const handleDelete = (product: Product) => {
    message.success(`产品 ${product.name} 已删除`);
  };
  
  const handleExport = () => {
    message.success('开始导出数据');
  };
  
  return (
    
} onClick={handleCreate} > 添加产品 } onClick={handleExport} > 导出数据 } /> columns={columns} dataSource={mockProducts} rowKey="id" search={false} options={{ density: true, reload: true }} pagination={{ pageSize: 10, }} />
无权查看产品列表 请联系管理员获取访问权限
产品统计报表

总销售额: $12,500

总库存: 55

} onClick={handleExport} style={{ marginTop: 16 }} > 导出报表
{/* 权限提示 */}
访问受限 您没有查看产品列表或报表的权限 {currentUser?.role && ( 当前角色: {currentUser.role} )}
); }; export default ProductPage;

权限配置文件

src/access.ts 中定义权限规则:

// src/access.ts
import type { InitialState } from './app';

export default function access(initialState: { initialState?: InitialState }): Record {
  const { currentUser } = initialState?.initialState ?? {};
  
  // 角色权限映射
  const rolePermissions = {
    admin: ['canView', 'canCreate', 'canEdit', 'canDelete', 'canExport'],
    editor: ['canView', 'canCreate', 'canEdit'],
    viewer: ['canView'],
  };
  
  // 如果没有当前用户,则认为没有任何权限
  if (!currentUser) {
    return {
      canView: false,
      canCreate: false,
      canEdit: false,
      canDelete: false,
      canExport: false,
    };
  }
  
  // 根据用户角色返回权限对象
  const permissions = {
    canView: rolePermissions[currentUser.role]?.includes('canView') || false,
    canCreate: rolePermissions[currentUser.role]?.includes('canCreate') || false,
    canEdit: rolePermissions[currentUser.role]?.includes('canEdit') || false,
    canDelete: rolePermissions[currentUser.role]?.includes('canDelete') || false,
    canExport: rolePermissions[currentUser.role]?.includes('canExport') || false,
  };
  
  return permissions;
}

全局状态配置 (models)

src/models/global.ts 中管理用户信息:

// src/models/global.ts
import { useState } from 'react';

export type GlobalState = {
  currentUser?: User;
};

export type User = {
  id: string;
  name: string;
  role: 'admin' | 'editor' | 'viewer';
  department?: string;
};

export default () => {
  const [global, setGlobal] = useState(() => ({
    currentUser: {
      id: '001',
      name: '管理员',
      role: 'admin',
      department: '技术部',
    },
  }));

  return {
    global,
    setGlobal,
  };
};

权限系统特点

1. 多层级权限控制

控制层级 实现方式 适用场景
页面级 Access 组件 控制整个模块或页面的访问权限
区域级 Access + 条件渲染 控制页面中的特定区域
按钮级 AuthButton 组件 控制单个操作按钮

2. 权限按钮的类型支持

// 普通按钮

  创建


// 危险操作(带确认框)

  删除


// 图标按钮
} 
  shape="circle"
/>

3. 权限状态反馈

用户状态 UI 表现 代码实现
无权限查看内容 展示提示信息 Access 组件的 accessible 属性
无操作权限 按钮不显示 AuthButton 内部处理
特殊权限需求 提示联系管理员 自定义无权限提示组件

4. 权限规则拓展

可以通过修改 access.ts 增加更多维度权限控制:

// 基于角色的权限控制
const permissions = {
  // ...
  canApprove: currentUser.role === 'admin',
};

// 基于部门的条件权限
if (currentUser.department === '财务部') {
  permissions.canCreate = false;
}

// 基于时间/条件的权限
const now = new Date();
permissions.canExport = permissions.canExport && now.getHours() > 9 && now.getHours() < 18;

最佳实践建议

  1. 权限划分原则

    • 使用 RBAC(基于角色的访问控制)作为基础
    • 每个按钮对应一个明确的权限点
    • 权限键名使用 canXxx 格式保持清晰
  2. API 级权限验证

    // 在 services 中增加权限验证
    export async function deleteProduct(id: string) {
      // 检查前端权限
      const access = useAccess();
      if (!access.canDelete) {
        throw new Error('无权执行此操作');
      }
      
      return request(`/api/products/${id}`, {
        method: 'DELETE',
      });
    }
  3. 敏感操作二次确认

  4. 权限审计功能

    // 添加权限变更日志
    function handlePermissionChange() {
      console.log(`[权限变更] 用户 ${currentUser.name} 尝试操作 ${action}`);
      // 发送到审计服务...
    }
  5. 按需加载大权限系统

    // 动态加载特殊权限模块
    const AdminPanel = React.lazy(() => import('./AdminPanel'));
    
    
      }>
        
      
    

权限状态可视化

AntDesignPro权限按钮实战指南_第1张图片

这个基于 Ant Design Pro 和 TypeScript 的权限按钮系统提供了完整的解决方案:

  • 精细的按钮级权限控制
  • 清晰的类型定义支持
  • 多种权限反馈机制
  • 灵活的规则扩展能力
  • 安全的操作确认流程

在实际企业项目中,这样的权限系统可以覆盖 95% 以上的权限控制场景,并通过合理的模块划分保持代码的可维护性和可扩展性。

你可能感兴趣的:(ant,design,pro,react,typescript,前端)