'use client'; import { useEffect, useMemo, useState } from 'react'; import { Plus, X, Shield } from 'lucide-react'; import { useMemberStore } from '@/stores/useMemberStore'; import { PERMISSION_GROUPS, ALL_PERMISSIONS } from '@/lib/permissions'; import { RouteGuard, useHasPermission } from '@/components/auth/Guard'; import type { RoleItem } from '@/lib/members'; export default function RolesPage() { return ( ); } function RolesPageContent() { const { roles, fetchMembers, createRole, updateRole, deleteRole } = useMemberStore(); const [showModal, setShowModal] = useState(false); const [editing, setEditing] = useState(null); const canCreate = useHasPermission('role:create'); const canEdit = useHasPermission('role:edit'); const canDelete = useHasPermission('role:delete'); useEffect(() => { fetchMembers(); }, [fetchMembers]); return (

角色管理

{roles.length}
{roles.map((role) => (
{role.name} {role.isSystem && ( 系统 )} {role.permissions.includes('*') ? '全部权限' : `${role.permissions.length} 项权限`}
{role.description && (

{role.description}

)}
{!role.isSystem && canDelete && ( )}
))}
{showModal && ( setShowModal(false)} onSubmit={(data) => { if (editing) updateRole(editing.id, data); else createRole(data); setShowModal(false); }} /> )}
); } function RoleModal({ initial, onClose, onSubmit }: { initial: RoleItem | null; onClose: () => void; onSubmit: (data: { name: string; description?: string; permissions: string[] }) => void; }) { const [name, setName] = useState(initial?.name ?? ''); const [description, setDescription] = useState(initial?.description ?? ''); const [permissions, setPermissions] = useState>(new Set(initial?.permissions ?? [])); const isReadOnly = !!initial?.isSystem; const isAdminWildcard = permissions.has('*'); const togglePerm = (p: string) => { if (isReadOnly) return; const next = new Set(permissions); if (next.has(p)) next.delete(p); else next.add(p); setPermissions(next); }; const handleSelectAll = () => setPermissions(new Set(ALL_PERMISSIONS)); const handleSelectNone = () => setPermissions(new Set()); const handleViewOnly = () => { const viewOnly = ALL_PERMISSIONS.filter((p) => p.endsWith(':view')); setPermissions(new Set(viewOnly)); }; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!name.trim() || isReadOnly) return; onSubmit({ name: name.trim(), description: description.trim() || undefined, permissions: Array.from(permissions) }); }; const mainGroups = useMemo(() => PERMISSION_GROUPS.filter((g) => g.category === 'main'), []); const tabGroups = useMemo(() => PERMISSION_GROUPS.filter((g) => g.category === 'version_tab'), []); return (
e.stopPropagation()}>

{initial ? (isReadOnly ? '查看角色' : '编辑角色') : '新建角色'}

{isReadOnly && (
系统角色不可修改,权限为系统预设
)}
setName(e.target.value)} required disabled={isReadOnly} placeholder="如:项目经理" className="h-9 w-full rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-[13px] focus:border-[var(--accent)] focus:outline-none disabled:bg-zinc-50 disabled:text-[var(--ink-soft)]" />
setDescription(e.target.value)} disabled={isReadOnly} placeholder="可选" className="h-9 w-full rounded-lg border border-[var(--line)] bg-[var(--bg-card)] px-3 text-[13px] focus:border-[var(--accent)] focus:outline-none disabled:bg-zinc-50 disabled:text-[var(--ink-soft)]" />
{!isReadOnly && (
)}
{isAdminWildcard ? (
此角色拥有所有权限(通配符 *)
) : (
)}
{!isReadOnly && ( )}
); } function PermissionSection({ title, groups, permissions, togglePerm, disabled }: { title: string; groups: typeof PERMISSION_GROUPS; permissions: Set; togglePerm: (p: string) => void; disabled: boolean; }) { return (
{title}
{groups.map((g) => (
{g.moduleLabel}
{g.actions.map((a) => ( ))}
))}
); }