"use client" import * as React from "react" import { useQuery, useMutation, gql } from '@apollo/client'; import { IconShield, IconKey, IconCheck, IconX, IconSettings, } from "@tabler/icons-react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Checkbox } from "@/components/ui/checkbox" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { toast } from "sonner" const GET_ROLES_WITH_PERMISSIONS = gql` query GetRolesWithPermissions { roles(pagination: { page: 1, perPage: 100 }) { items { id name code level isActive permissions { id name code module action resource } } } } ` const GET_ALL_PERMISSIONS = gql` query GetAllPermissions { permissions(pagination: { page: 1, perPage: 500 }) { items { id name code description module action resource level isActive } } } ` const ADD_POLICY = gql` mutation AddPolicy($roleName: String!, $resource: String!, $action: String!) { addPolicy(roleName: $roleName, resource: $resource, action: $action) } ` const REMOVE_POLICY = gql` mutation RemovePolicy($roleName: String!, $resource: String!, $action: String!) { removePolicy(roleName: $roleName, resource: $resource, action: $action) } ` interface Permission { id: string name: string code: string description?: string module: string action: string resource: string level: number isActive: boolean } interface Role { id: string name: string code: string level: number isActive: boolean permissions: Permission[] } const getActionColor = (action: string) => { switch (action.toLowerCase()) { case 'create': return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300' case 'read': return 'bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-300' case 'update': return 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-300' case 'delete': return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300' default: return 'bg-gray-100 text-gray-800 dark:bg-gray-900 dark:text-gray-300' } } function PermissionMatrix({ roles, permissions, onPermissionChange }: { roles: Role[] permissions: Permission[] onPermissionChange: () => void }) { const [addPolicy] = useMutation(ADD_POLICY) const [removePolicy] = useMutation(REMOVE_POLICY) const [selectedModule, setSelectedModule] = React.useState("") const modules = Array.from(new Set(permissions.map(p => p.module))) const filteredPermissions = selectedModule ? permissions.filter(p => p.module === selectedModule) : permissions const handlePermissionToggle = async (roleId: string, permissionId: string, hasPermission: boolean) => { const role = roles.find(r => r.id === roleId) const permission = permissions.find(p => p.id === permissionId) if (!role || !permission) return try { if (hasPermission) { await removePolicy({ variables: { roleName: role.code, resource: permission.resource, action: permission.action } }) toast.success("权限移除成功") } else { await addPolicy({ variables: { roleName: role.code, resource: permission.resource, action: permission.action } }) toast.success("权限分配成功") } onPermissionChange() } catch (error) { toast.error("操作失败") } } const hasPermission = (role: Role, permissionId: string) => { return role.permissions.some(p => p.id === permissionId) } return ( 权限矩阵 查看和管理角色与权限的对应关系
共 {filteredPermissions.length} 个权限
权限 {roles.filter(r => r.isActive).map((role) => (
{role.name}
Level {role.level}
))}
{filteredPermissions.map((permission) => (
{permission.name}
{permission.code}
{permission.module} {permission.action}
{roles.filter(r => r.isActive).map((role) => { const roleHasPermission = hasPermission(role, permission.id) const canModify = permission.level <= role.level return ( ) })}
))}
) } function RolePermissionEditor({ role, allPermissions, onSave }: { role: Role allPermissions: Permission[] onSave: () => void }) { const [open, setOpen] = React.useState(false) const [selectedPermissions, setSelectedPermissions] = React.useState( role.permissions.map(p => p.id) ) const [searchTerm, setSearchTerm] = React.useState("") const [moduleFilter, setModuleFilter] = React.useState("") const [loading, setLoading] = React.useState(false) const filteredPermissions = allPermissions.filter(permission => { const matchesSearch = permission.name.toLowerCase().includes(searchTerm.toLowerCase()) || permission.code.toLowerCase().includes(searchTerm.toLowerCase()) const matchesModule = !moduleFilter || permission.module === moduleFilter return matchesSearch && matchesModule && permission.isActive }) const modules = Array.from(new Set(allPermissions.map(p => p.module))) const handlePermissionToggle = (permissionId: string) => { setSelectedPermissions(prev => prev.includes(permissionId) ? prev.filter(id => id !== permissionId) : [...prev, permissionId] ) } const handleSelectAll = () => { const allIds = filteredPermissions.map(p => p.id) setSelectedPermissions(prev => { const hasAll = allIds.every(id => prev.includes(id)) if (hasAll) { return prev.filter(id => !allIds.includes(id)) } else { return Array.from(new Set([...prev, ...allIds])) } }) } const handleSave = async () => { toast.info("批量保存功能正在开发中,请使用权限矩阵进行单个权限操作") setOpen(false) } React.useEffect(() => { if (open) { setSelectedPermissions(role.permissions.map(p => p.id)) } }, [open, role.permissions]) return ( 编辑角色权限 - {role.name} 为角色 "{role.name}" 配置权限。选中的权限将被分配给该角色。
setSearchTerm(e.target.value)} className="flex-1" />
已选择 {selectedPermissions.length} 个权限 共 {filteredPermissions.length} 个权限
{filteredPermissions.map((permission) => (
handlePermissionToggle(permission.id)} />
{permission.name} {permission.module} {permission.action}
{permission.code} - {permission.description || "无描述"}
Level {permission.level}
))}
) } export function RolePermissionManagement() { const [selectedRole, setSelectedRole] = React.useState("") const { data: rolesData, loading: rolesLoading, refetch: refetchRoles } = useQuery(GET_ROLES_WITH_PERMISSIONS, { fetchPolicy: 'cache-and-network' }) const { data: permissionsData, loading: permissionsLoading } = useQuery(GET_ALL_PERMISSIONS, { fetchPolicy: 'cache-and-network' }) const roles = rolesData?.roles?.items || [] const permissions = permissionsData?.permissions?.items || [] const activeRoles = roles.filter(r => r.isActive) const currentRole = selectedRole ? roles.find(r => r.id === selectedRole) : null return (
{/* 角色概览卡片 */}
{activeRoles.map((role) => ( setSelectedRole(selectedRole === role.id ? "" : role.id)} >
{role.name}
Level {role.level}
{role.code}
权限数: {role.permissions.length}
))}
{/* 选中角色的权限详情 */} {currentRole && ( {currentRole.name} 的权限详情 查看角色 "{currentRole.name}" 当前拥有的所有权限 {currentRole.permissions.length === 0 ? (

暂无权限

该角色尚未分配任何权限。

) : (
共 {currentRole.permissions.length} 个权限
{currentRole.permissions.map((permission) => (
{permission.name}
{permission.code}
{permission.module} {permission.action}
))}
)}
)} {/* 权限矩阵 */} {!rolesLoading && !permissionsLoading && ( )}
) }