import { Button, Card, Col, Empty, Input, message, Row, Space, Table, Tag, Tree, Typography } from "antd"; import type { DataNode } from "antd/es/tree"; import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { ClusterOutlined, KeyOutlined, SafetyCertificateOutlined, SaveOutlined, SearchOutlined } from "@ant-design/icons"; import { listPermissions, listRolePermissions, listRoles, saveRolePermissions } from "@/api"; import PageHeader from "@/components/shared/PageHeader"; import { getStandardPagination } from "@/utils/pagination"; import type { SysPermission, SysRole } from "@/types"; const { Text } = Typography; type PermissionNode = SysPermission & { key: number; children?: PermissionNode[] }; function buildPermissionTree(list: SysPermission[]): PermissionNode[] { if (!list.length) return []; const active = list.filter((item) => item.status !== 0); const map = new Map(); const roots: PermissionNode[] = []; active.forEach((item) => { map.set(item.permId, { ...item, key: item.permId, children: [] }); }); map.forEach((node) => { if (node.parentId && node.parentId !== 0) { const parent = map.get(node.parentId); if (parent) { parent.children!.push(node); } } else { roots.push(node); } }); const sortNodes = (nodes: PermissionNode[]) => { nodes.sort((left, right) => (left.sortOrder || 0) - (right.sortOrder || 0)); nodes.forEach((node) => { if (node.children?.length) { sortNodes(node.children); } }); }; sortNodes(roots); return roots; } function toTreeData(nodes: PermissionNode[]): DataNode[] { return nodes.map((node) => ({ key: node.permId, title: ( {node.name} {node.permType === "button" ? ( Button ) : null} ), children: node.children?.length ? toTreeData(node.children) : undefined })); } export default function RolePermissionBinding() { const { t } = useTranslation(); const [roles, setRoles] = useState([]); const [permissions, setPermissions] = useState([]); const [loadingRoles, setLoadingRoles] = useState(false); const [loadingPerms, setLoadingPerms] = useState(false); const [saving, setSaving] = useState(false); const [selectedRoleId, setSelectedRoleId] = useState(null); const [checkedPermIds, setCheckedPermIds] = useState([]); const [halfCheckedIds, setHalfCheckedIds] = useState([]); const [searchText, setSearchText] = useState(""); const isPlatformMode = useMemo(() => { const profileStr = sessionStorage.getItem("userProfile"); if (!profileStr) { return false; } const profile = JSON.parse(profileStr); return !!profile.isPlatformAdmin; }, []); const selectedRole = useMemo( () => roles.find((role) => role.roleId === selectedRoleId) || null, [roles, selectedRoleId] ); const filteredRoles = useMemo(() => { if (!searchText) { return roles; } const lower = searchText.toLowerCase(); return roles.filter((role) => role.roleName.toLowerCase().includes(lower) || role.roleCode.toLowerCase().includes(lower)); }, [roles, searchText]); const treeData = useMemo(() => toTreeData(buildPermissionTree(permissions)), [permissions]); const loadRoles = async () => { setLoadingRoles(true); try { const list = await listRoles(); setRoles(list || []); } finally { setLoadingRoles(false); } }; const loadPermissions = async () => { setLoadingPerms(true); try { const list = await listPermissions(); setPermissions(list || []); } finally { setLoadingPerms(false); } }; const loadRolePermissions = async (roleId: number) => { try { const list = await listRolePermissions(roleId); const normalized = (list || []).map((id) => Number(id)).filter((id) => !Number.isNaN(id)); const leafIds = normalized.filter((id) => !permissions.some((permission) => permission.parentId === id)); setCheckedPermIds(leafIds); setHalfCheckedIds([]); } catch { setCheckedPermIds([]); setHalfCheckedIds([]); } }; useEffect(() => { loadRoles(); loadPermissions(); }, []); useEffect(() => { if (selectedRoleId && permissions.length > 0) { loadRolePermissions(selectedRoleId); } else { setCheckedPermIds([]); setHalfCheckedIds([]); } }, [selectedRoleId, permissions]); const handleSave = async () => { if (!selectedRoleId) { message.warning(t("rolePerm.selectRole")); return; } setSaving(true); try { await saveRolePermissions(selectedRoleId, Array.from(new Set([...checkedPermIds, ...halfCheckedIds]))); message.success(t("common.success")); } finally { setSaving(false); } }; return (