108 lines
2.9 KiB
TypeScript
108 lines
2.9 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
|
|
import type { PlatformPermission, Role } from "../../services/api";
|
|
import {
|
|
AppFormDialog,
|
|
dialogPrimaryButtonClass,
|
|
dialogSecondaryButtonClass,
|
|
} from "~/components/common/AppFormDialog";
|
|
import { Button } from "~/components/ui/button";
|
|
import { modalFormClass } from "../platform/modalUi";
|
|
import { PermissionCheckboxList } from "./PermissionCheckboxList";
|
|
|
|
export function PermissionEditDialog({
|
|
open,
|
|
target,
|
|
permissions,
|
|
currentCodes,
|
|
saving,
|
|
onSubmit,
|
|
onClose,
|
|
}: {
|
|
open: boolean;
|
|
target: Role | null;
|
|
permissions: PlatformPermission[];
|
|
currentCodes: string[];
|
|
saving: boolean;
|
|
onSubmit: (codes: string[]) => void;
|
|
onClose: () => void;
|
|
}) {
|
|
const [selectedCodes, setSelectedCodes] = useState<string[]>(() => {
|
|
if (!open || !target) return [];
|
|
const initial = [...currentCodes];
|
|
if (target.role_code === "admin" && !initial.includes("system:view")) {
|
|
initial.push("system:view");
|
|
}
|
|
return initial;
|
|
});
|
|
|
|
useEffect(() => {
|
|
const initial = [...currentCodes];
|
|
if (target?.role_code === "admin" && !initial.includes("system:view")) {
|
|
initial.push("system:view");
|
|
}
|
|
setSelectedCodes(initial);
|
|
}, [open, target, currentCodes]);
|
|
|
|
const togglePermission = (code: string): void => {
|
|
if (!target) return;
|
|
const locked = target.role_code === "admin"
|
|
? code === "system:view"
|
|
: code.startsWith("system:");
|
|
if (locked) return;
|
|
setSelectedCodes((current) =>
|
|
current.includes(code)
|
|
? current.filter((item) => item !== code)
|
|
: [...current, code],
|
|
);
|
|
};
|
|
|
|
return (
|
|
<AppFormDialog
|
|
open={open && target !== null}
|
|
onOpenChange={(nextOpen) => {
|
|
if (!nextOpen) onClose();
|
|
}}
|
|
eyebrow="PERMISSIONS"
|
|
title={target ? `权限配置 · ${target.role_name}` : "权限配置"}
|
|
footer={
|
|
<>
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
type="button"
|
|
onClick={onClose}
|
|
className={dialogSecondaryButtonClass}
|
|
>
|
|
取消
|
|
</Button>
|
|
<Button
|
|
variant="default"
|
|
size="sm"
|
|
type="button"
|
|
disabled={saving}
|
|
onClick={() => onSubmit(selectedCodes)}
|
|
className={dialogPrimaryButtonClass}
|
|
>
|
|
{saving ? "保存中…" : "保存权限"}
|
|
</Button>
|
|
</>
|
|
}
|
|
>
|
|
<div className={modalFormClass}>
|
|
{target?.role_code === "admin" && (
|
|
<p className="role-error">admin 角色必须保留 system:view 权限。</p>
|
|
)}
|
|
{target ? (
|
|
<PermissionCheckboxList
|
|
permissions={permissions}
|
|
selected={selectedCodes}
|
|
targetRoleCode={target.role_code}
|
|
onToggle={togglePermission}
|
|
/>
|
|
) : null}
|
|
</div>
|
|
</AppFormDialog>
|
|
);
|
|
}
|