import { PermTree } from '@/pages/Admin/_shared/PermTree'; import { calcUserPermDelta } from '@/pages/Admin/_shared/PermTree/lib/permUtils'; import { fetchMemberUserProducts } from '@/services/member'; import { fetchPermList } from '@/services/perm'; import { fetchRoleDetail } from '@/services/role'; import { fetchGetUserPerms, fetchSetUserPerms, fetchUserDetail } from '@/services/user'; import { Button, Drawer, Modal, Select, Spin, message } from 'antd'; import { useEffect, useState } from 'react'; interface UserPermDrawerProps { userId: number; open: boolean; onClose: () => void; } export const UserPermDrawer = ({ userId, open, onClose }: UserPermDrawerProps) => { const [products, setProducts] = useState([]); const [productCode, setProductCode] = useState(); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const [allPerms, setAllPerms] = useState([]); const [checkedIds, setCheckedIds] = useState([]); const [initialCheckedIds, setInitialCheckedIds] = useState([]); const [roleInheritedIds, setRoleInheritedIds] = useState([]); useEffect(() => { if (!open) return; setProductCode(undefined); setAllPerms([]); setCheckedIds([]); setInitialCheckedIds([]); setRoleInheritedIds([]); fetchMemberUserProducts({ userId }).then((res) => { const list = res.data?.list ?? []; setProducts(list); if (list.length > 0) setProductCode(list[0].productCode); }); }, [open]); useEffect(() => { if (!open || !productCode) return; setLoading(true); const load = async () => { const [userRes, permRes, userPermsRes] = await Promise.all([ fetchUserDetail({ id: userId }), fetchPermList({ productCode, pageSize: 9999 }), fetchGetUserPerms({ userId }), ]); const perms = permRes.data ?? []; setAllPerms(perms); const permIdSet = new Set(perms.map((p: API.PermItem) => p.id)); const userPerms = userPermsRes.data?.perms ?? []; const allowIds = new Set( userPerms .filter((p) => p.effect === 'ALLOW') .map((p) => p.permId) .filter((id) => permIdSet.has(id)), ); const denyIds = new Set(userPerms.filter((p) => p.effect === 'DENY').map((p) => p.permId)); const roleIds = userRes.data?.roleIds ?? []; const roleDetails = await Promise.all(roleIds.map((id) => fetchRoleDetail({ id }))); const inherited = new Set(); roleDetails.forEach((r) => (r.data?.permIds ?? []).forEach((id) => inherited.add(id))); setRoleInheritedIds([...inherited]); const effective = [...inherited, ...allowIds].filter((id) => !denyIds.has(id)); setCheckedIds([...new Set(effective)]); setInitialCheckedIds([...new Set(effective)]); }; load().finally(() => setLoading(false)); }, [open, userId, productCode]); const isDirty = checkedIds.length !== initialCheckedIds.length || checkedIds.some((id) => !initialCheckedIds.includes(id)); const handleProductChange = (code: string) => { if (productCode && isDirty) { Modal.confirm({ title: '未保存的修改', content: '当前产品的权限设置已修改但未保存,切换将丢失修改。确认切换?', okText: '确认切换', cancelText: '取消', onOk: () => setProductCode(code), }); return; } setProductCode(code); }; const handleSave = async () => { setSaving(true); try { const perms = calcUserPermDelta(checkedIds, roleInheritedIds); await fetchSetUserPerms({ userId, perms }); message.success('保存成功'); onClose(); } finally { setSaving(false); } }; return ( } > {products.length === 0 ? ( 用户不属于任何产品,无法设置权限 ) : ( <>