feat(s2a): Add expandable group list with truncation in ProfileCard

- Add expanded state to ProfileCard component for toggling group visibility
- Implement MAX_VISIBLE constant to limit initial group display to 4 items
- Add toggle button to show/hide remaining groups with count indicator
- Display "收起" (collapse) when expanded, "+N 个分组" (N groups) when collapsed
- Wrap group grid in container div to accommodate expand/collapse button
- Improve UX for profiles with many groups by preventing excessive card height
This commit is contained in:
2026-02-07 20:43:44 +08:00
parent f74c421fd8
commit 231611af84

View File

@@ -598,10 +598,15 @@ function ProfileCard({ profile, isActive, isActivating, groupNameCache, onActiva
onDelete: () => void onDelete: () => void
}) { }) {
const [confirming, setConfirming] = useState(false) const [confirming, setConfirming] = useState(false)
const [expanded, setExpanded] = useState(false)
let parsedGroups: number[] = [] let parsedGroups: number[] = []
try { parsedGroups = JSON.parse(profile.group_ids || '[]') } catch { /* ignore */ } try { parsedGroups = JSON.parse(profile.group_ids || '[]') } catch { /* ignore */ }
const MAX_VISIBLE = 4
const visibleGroups = expanded ? parsedGroups : parsedGroups.slice(0, MAX_VISIBLE)
const hiddenCount = parsedGroups.length - MAX_VISIBLE
return ( return (
<Card className={`relative transition-all flex flex-col h-full ${isActive ? 'ring-2 ring-green-500 dark:ring-green-400' : ''}`}> <Card className={`relative transition-all flex flex-col h-full ${isActive ? 'ring-2 ring-green-500 dark:ring-green-400' : ''}`}>
{/* 活动标记 */} {/* 活动标记 */}
@@ -636,14 +641,24 @@ function ProfileCard({ profile, isActive, isActivating, groupNameCache, onActiva
{/* 分组列表 */} {/* 分组列表 */}
{parsedGroups.length > 0 && ( {parsedGroups.length > 0 && (
<div className="grid grid-cols-2 gap-2 mb-4"> <div className="mb-4">
{parsedGroups.map(id => ( <div className="grid grid-cols-2 gap-2">
{visibleGroups.map(id => (
<div key={id} className="flex flex-col px-2.5 py-1.5 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-100 dark:border-blue-800/40"> <div key={id} className="flex flex-col px-2.5 py-1.5 rounded-lg bg-blue-50 dark:bg-blue-900/20 border border-blue-100 dark:border-blue-800/40">
<span className="text-xs font-medium text-blue-700 dark:text-blue-300 truncate">{groupNameCache[id] || `#${id}`}</span> <span className="text-xs font-medium text-blue-700 dark:text-blue-300 truncate">{groupNameCache[id] || `#${id}`}</span>
{groupNameCache[id] && <span className="text-[10px] text-blue-400 dark:text-blue-500">#{id}</span>} {groupNameCache[id] && <span className="text-[10px] text-blue-400 dark:text-blue-500">#{id}</span>}
</div> </div>
))} ))}
</div> </div>
{hiddenCount > 0 && (
<button
onClick={() => setExpanded(!expanded)}
className="mt-2 text-xs text-blue-500 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300 transition-colors"
>
{expanded ? '收起' : `+${hiddenCount} 个分组`}
</button>
)}
</div>
)} )}
{/* 操作按钮 */} {/* 操作按钮 */}