import { useEffect, useState } from "react"; import { Plus, Search } from "lucide-react"; import { ApiRequestError, type PlatformPermission, type Role, type RoleCreatePayload, type RoleUpdatePayload, } from "../../services/api"; import { useApi, useAuth } from "../../context/AuthContext"; import { Button } from "~/components/ui/button"; import { PermissionEditDialog } from "./PermissionEditDialog"; import { RoleEditDialog } from "./RoleEditDialog"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "~/components/ui/table"; import { AdminColgroup, ROLE_COL_WIDTHS } from "./AdminTable"; import "../../styles/admin.css"; export function RoleManagementPage({ onNotify, onConnectionChange, }: { onNotify: (notice: { tone: "success" | "error" | "info"; message: string }) => void; onConnectionChange: (online: boolean) => void; }) { const api = useApi(); const { user } = useAuth(); const [roles, setRoles] = useState([]); const [permissions, setPermissions] = useState([]); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [loadError, setLoadError] = useState(null); const [searchTerm, setSearchTerm] = useState(""); // 新建 / 编辑弹窗 const [dialogOpen, setDialogOpen] = useState(false); const [editing, setEditing] = useState(null); // 权限配置弹窗 const [permissionDialogOpen, setPermissionDialogOpen] = useState(false); const [permissionTarget, setPermissionTarget] = useState(null); const canManage = user?.role_code === "admin"; const load = async (): Promise => { setLoading(true); setLoadError(null); try { const [roleList, permissionList] = await Promise.all([ api.listPlatformRoles(), api.listPlatformPermissions(), ]); setRoles(roleList); setPermissions(permissionList); onConnectionChange(true); } catch (error) { onConnectionChange(false); const message = error instanceof Error ? error.message : "角色列表加载失败"; setLoadError(message); onNotify({ tone: "error", message }); } finally { setLoading(false); } }; useEffect(() => { void load(); }, []); const openCreate = (): void => { setEditing(null); setDialogOpen(true); }; const openEdit = (role: Role): void => { setEditing(role); setDialogOpen(true); }; const openPermissions = (role: Role): void => { setPermissionTarget(role); setPermissionDialogOpen(true); }; const handleRoleSubmit = async ( payload: RoleCreatePayload | RoleUpdatePayload, ): Promise => { setSaving(true); try { if (editing) { const updated = await api.updatePlatformRole( editing.role_code, payload as RoleUpdatePayload, ); setRoles((current) => current.map( (item) => item.role_code === updated.role_code ? updated : item, )); onNotify({ tone: "success", message: "角色信息已更新" }); } else { const created = await api.createPlatformRole( payload as RoleCreatePayload, ); setRoles((current) => [...current, created]); onNotify({ tone: "success", message: "角色已创建" }); } setDialogOpen(false); } catch (error) { onNotify({ tone: "error", message: error instanceof ApiRequestError ? error.message : (editing ? "保存角色失败" : "创建角色失败"), }); } finally { setSaving(false); } }; const savePermissions = async (codes: string[]): Promise => { if (!permissionTarget) return; setSaving(true); try { const updated = await api.updatePlatformRolePermissions( permissionTarget.role_code, codes, ); setRoles((current) => current.map( (item) => item.role_code === updated.role_code ? updated : item, )); onNotify({ tone: "success", message: "权限已保存" }); setPermissionDialogOpen(false); } catch (error) { onNotify({ tone: "error", message: error instanceof ApiRequestError ? error.message : "保存权限失败", }); } finally { setSaving(false); } }; const removeRole = async (role: Role): Promise => { if (role.is_builtin) return; if (!window.confirm(`确定删除角色"${role.role_name}"吗?`)) return; try { await api.deletePlatformRole(role.role_code); setRoles((current) => current.filter( (item) => item.role_code !== role.role_code, )); onNotify({ tone: "success", message: "角色已删除" }); } catch (error) { onNotify({ tone: "error", message: error instanceof Error ? error.message : "删除角色失败", }); } }; const filteredRoles = roles.filter((role) => { const term = searchTerm.toLowerCase().trim(); if (!term) return true; return ( role.role_code.toLowerCase().includes(term) || role.role_name.toLowerCase().includes(term) ); }); return (
setSearchTerm(event.target.value)} />
{!canManage && (
当前为开发人员,只能查看角色列表。
)} {loadError &&
{loadError}
} 角色编码 角色名称 类型 权限 操作 {loading ? (

正在加载角色…

) : filteredRoles.length === 0 ? (

{roles.length === 0 ? "暂无角色" : "没有匹配的角色"}

) : ( filteredRoles.map((role) => ( {role.role_code} {role.role_name} {role.is_builtin ? "内置" : "自定义"} {role.permission_codes.length} 项权限 )) )}
{dialogOpen && ( void handleRoleSubmit(payload)} onClose={() => setDialogOpen(false)} /> )} {permissionDialogOpen && permissionTarget && ( void savePermissions(codes)} onClose={() => setPermissionDialogOpen(false)} /> )}
); }