import { useEffect, useMemo, useState } from 'react'; import { Alert, Button, Card, Checkbox, Col, Form, Row, Select, Space, Tabs, Tag, Typography, message, } from 'antd'; import { HQ_ADMIN_ROLES, HQ_PERMISSION_CATALOG, type HqPermissionKey, } from '@dukang/shared-types'; import { request, type HqProfile } from '../lib/api'; type RolePermRes = { role: string; permissionKeys: string[] }; type AccountOption = { id: string; name: string; phone: string; loginName: string | null; adminRole: string }; type AccountPermRes = { account: AccountOption; permissionKeys: string[]; rolePermissionKeys: string[]; userPermissionKeys: string[]; effectivePermissionKeys: string[]; }; const ROLE_LABELS = Object.fromEntries(HQ_ADMIN_ROLES.map((r) => [r.value, r.label])); const CATALOG_GROUPS = [...new Set(HQ_PERMISSION_CATALOG.map((p) => p.group ?? '其他'))]; function groupColSpan(itemCount: number): number { if (itemCount <= 2) return 12; if (itemCount === 3) return 8; if (itemCount === 4) return 6; return 8; } function PermissionChecklist({ value, onChange, disabled, }: { value: string[]; onChange: (keys: string[]) => void; disabled?: boolean; }) { return ( onChange(checked as string[])} > {CATALOG_GROUPS.map((group) => { const items = HQ_PERMISSION_CATALOG.filter((p) => (p.group ?? '其他') === group); const span = groupColSpan(items.length); const compact = items.length <= 3; return (
{group} {compact ? ( {items.map((item) => ( {item.label} ))} ) : ( {items.map((item) => ( {item.label} ))} )}
); })}
); } export default function HqPermissionsPage() { const [profile, setProfile] = useState(null); const [role, setRole] = useState('OPS'); const [roleKeys, setRoleKeys] = useState([]); const [roleLoading, setRoleLoading] = useState(false); const [roleSaving, setRoleSaving] = useState(false); const [accounts, setAccounts] = useState([]); const [accountId, setAccountId] = useState(); const [accountKeys, setAccountKeys] = useState([]); const [roleInheritedKeys, setRoleInheritedKeys] = useState([]); const [accountLoading, setAccountLoading] = useState(false); const [accountSaving, setAccountSaving] = useState(false); const selectedAccount = useMemo( () => accounts.find((a) => a.id === accountId), [accounts, accountId], ); const selectedIsSuperAdmin = selectedAccount?.adminRole === 'SUPER_ADMIN'; const previewEffectiveKeys = useMemo( () => [...new Set([...roleInheritedKeys, ...accountKeys])], [roleInheritedKeys, accountKeys], ); const isSuperAdmin = profile?.adminRole === 'SUPER_ADMIN'; useEffect(() => { request('/admin/auth/me').then(setProfile).catch(() => {}); }, []); useEffect(() => { if (!isSuperAdmin) return; request<{ items: AccountOption[] }>('/admin/hq-accounts?page=1&pageSize=100') .then((res) => setAccounts(res.items)) .catch(() => {}); }, [isSuperAdmin]); useEffect(() => { if (!isSuperAdmin || !role) return; setRoleLoading(true); request(`/admin/hq-permissions/roles/${role}`) .then((res) => setRoleKeys(res.permissionKeys)) .finally(() => setRoleLoading(false)); }, [isSuperAdmin, role]); useEffect(() => { if (!isSuperAdmin || !accountId) return; setAccountLoading(true); request(`/admin/hq-permissions/accounts/${accountId}`) .then((res) => { setAccountKeys(res.userPermissionKeys); setRoleInheritedKeys(res.rolePermissionKeys); }) .finally(() => setAccountLoading(false)); }, [isSuperAdmin, accountId]); async function saveRolePermissions() { setRoleSaving(true); try { const res = await request(`/admin/hq-permissions/roles/${role}`, { method: 'PUT', body: JSON.stringify({ permissionKeys: roleKeys }), }); setRoleKeys(res.permissionKeys); message.success('角色权限已保存'); } catch (e) { message.error(e instanceof Error ? e.message : '保存失败'); } finally { setRoleSaving(false); } } async function saveAccountPermissions() { if (!accountId) return; setAccountSaving(true); try { const res = await request(`/admin/hq-permissions/accounts/${accountId}`, { method: 'PUT', body: JSON.stringify({ permissionKeys: accountKeys }), }); setAccountKeys(res.userPermissionKeys); setRoleInheritedKeys(res.rolePermissionKeys); message.success('用户权限已保存'); } catch (e) { message.error(e instanceof Error ? e.message : '保存失败'); } finally { setAccountSaving(false); } } if (!isSuperAdmin) { return (
权限分配
); } return (
权限分配 按角色配置基础权限;按用户可追加专属权限。最终生效权限 = 角色权限 ∪ 用户权限。 超级管理员默认拥有除「危险操作」外的全部权限;删除用户/订单/城市需在「按用户分配」中单独勾选(默认均无)。 「系统设置」已拆分为各配置分组;「财务」对应门店/合伙人/酒厂账单。
({ value: a.id, label: `${a.name} · ${a.loginName || a.phone} · ${ROLE_LABELS[a.adminRole] || a.adminRole}`, }))} />
{!accountId ? ( ) : ( <>
角色继承: {selectedIsSuperAdmin ? ( 超级管理员基础权限(不含危险操作) ) : ( {roleInheritedKeys.map((key) => { const item = HQ_PERMISSION_CATALOG.find((p) => p.key === key); return ( {item?.label || key} ); })} {!roleInheritedKeys.length ? ( ) : null} )}
下方勾选为用户专属追加权限(保存后与角色权限合并生效)。危险操作(删除用户/订单/城市)默认不授予,需在此勾选。
合并生效: {selectedIsSuperAdmin ? ( 基础权限(全部) {accountKeys.map((key) => { const item = HQ_PERMISSION_CATALOG.find((p) => p.key === (key as HqPermissionKey)); return ( {item?.label || key} ); })} ) : ( {previewEffectiveKeys.map((key) => { const item = HQ_PERMISSION_CATALOG.find((p) => p.key === (key as HqPermissionKey)); return ( {item?.label || key} ); })} )}
)} ), }, ]} />
); }