| 1 | import type { SocialAccount } from '@/api/accounts/account.types' |
| 2 | import type { AccountGroup } from '@/store/account' |
| 3 | import { DownOutlined, RightOutlined } from '@ant-design/icons' |
| 4 | import { Check } from 'lucide-react' |
| 5 | import { memo } from 'react' |
| 6 | import { useTransClient } from '@/app/i18n/client' |
| 7 | import { cn } from '@/utils/className' |
| 8 | import AccountItem from './AccountItem' |
| 9 | |
| 10 | interface SpaceGroupItemProps { |
| 11 | group: AccountGroup |
| 12 | accounts: SocialAccount[] |
| 13 | isCollapsed: boolean |
| 14 | isDefaultGroup: boolean |
| 15 | canMoveUp: boolean |
| 16 | canMoveDown: boolean |
| 17 | activeAccountId?: string |
| 18 | /** 当前选中的空间 ID */ |
| 19 | activeSpaceId?: string |
| 20 | sortLoading?: string | null |
| 21 | deleteLoading?: string | null |
| 22 | onToggleCollapse: (groupId: string) => void |
| 23 | onSelectAccount: (account: SocialAccount) => void |
| 24 | onGroupSort: (groupId: string, direction: 'up' | 'down') => void |
| 25 | /** 选择空间的回调 */ |
| 26 | onSpaceSelect?: (spaceId: string | undefined) => void |
| 27 | } |
| 28 | |
| 29 | const SpaceGroupItem = memo( |
| 30 | ({ |
| 31 | group, |
| 32 | accounts, |
| 33 | isCollapsed, |
| 34 | isDefaultGroup, |
| 35 | canMoveUp, |
| 36 | canMoveDown, |
| 37 | activeAccountId, |
| 38 | activeSpaceId, |
| 39 | sortLoading, |
| 40 | deleteLoading, |
| 41 | onToggleCollapse, |
| 42 | onSelectAccount, |
| 43 | onGroupSort, |
| 44 | onSpaceSelect, |
| 45 | }: SpaceGroupItemProps) => { |
| 46 | const { t } = useTransClient('account') |
| 47 | const isSorting = sortLoading === group.id |
| 48 | const isSpaceActive = activeSpaceId === group.id |
| 49 | |
| 50 | // 点击空间名称区域 - 选择/取消选择空间 |
| 51 | const handleSpaceClick = (e: React.MouseEvent) => { |
| 52 | e.stopPropagation() |
| 53 | if (onSpaceSelect) { |
| 54 | // 如果已选中,取消选择;否则选择该空间 |
| 55 | onSpaceSelect(isSpaceActive ? undefined : group.id) |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | // 点击箭头 - 展开/折叠 |
| 60 | const handleToggleClick = (e: React.MouseEvent) => { |
| 61 | e.stopPropagation() |
| 62 | onToggleCollapse(group.id) |
| 63 | } |
| 64 | |
| 65 | // 右键点击 - 展开/折叠 |
| 66 | const handleContextMenu = (e: React.MouseEvent) => { |
| 67 | e.preventDefault() |
| 68 | e.stopPropagation() |
| 69 | onToggleCollapse(group.id) |
| 70 | } |
| 71 | |
| 72 | return ( |
| 73 | <div className="mb-1"> |
| 74 | {/* 空间标题行 */} |
| 75 | <div |
| 76 | data-testid="accounts-selector-space-group" |
| 77 | className={cn( |
| 78 | 'flex items-center gap-2 px-3 py-2 transition-colors cursor-pointer', |
| 79 | isSpaceActive ? 'bg-primary/10 hover:bg-primary/15' : 'hover:bg-muted/50', |
| 80 | )} |
| 81 | onClick={handleSpaceClick} |
| 82 | onContextMenu={handleContextMenu} |
| 83 | > |
| 84 | {/* 箭头区域 - 点击展开/折叠 */} |
| 85 | <div className="p-0.5 rounded hover:bg-muted" onClick={handleToggleClick}> |
| 86 | {isCollapsed ? ( |
| 87 | <RightOutlined className="text-xs text-muted-foreground" /> |
| 88 | ) : ( |
| 89 | <DownOutlined className="text-xs text-muted-foreground" /> |
| 90 | )} |
| 91 | </div> |
| 92 | |
| 93 | {/* 空间名称 */} |
| 94 | <span |
| 95 | className={cn( |
| 96 | 'text-xs font-semibold flex-1', |
| 97 | isSpaceActive ? 'text-primary' : 'text-muted-foreground', |
| 98 | )} |
| 99 | > |
| 100 | {group.name || t('defaultSpace')} |
| 101 | </span> |
| 102 | |
| 103 | {/* 选中图标 */} |
| 104 | {isSpaceActive && <Check className="w-4 h-4 text-primary" />} |
| 105 | |
| 106 | {/* 账号数量 */} |
| 107 | <span className="text-xs text-muted-foreground">{accounts.length}</span> |
| 108 | </div> |
| 109 | |
| 110 | {/* 频道列表 */} |
| 111 | {!isCollapsed |
| 112 | && accounts.map((account) => { |
| 113 | const isActive = activeAccountId === account.id |
| 114 | return ( |
| 115 | <AccountItem |
| 116 | key={account.id} |
| 117 | account={account} |
| 118 | isActive={isActive} |
| 119 | onSelect={onSelectAccount} |
| 120 | indent |
| 121 | /> |
| 122 | ) |
| 123 | })} |
| 124 | </div> |
| 125 | ) |
| 126 | }, |
| 127 | ) |
| 128 | |
| 129 | SpaceGroupItem.displayName = 'SpaceGroupItem' |
| 130 | |
| 131 | export default SpaceGroupItem |
| 132 |