feat(分组): 成员改为方块网格,只显示中文名、全部铺开不滚动

反馈是「不要一行一个,只留中文名,做成方块,全展示不滚动」。

· 标签云 → 方块网格(grid + auto-fill,minmax(92px,1fr)):
  窗口越宽一行放得越多,每个成员一格,整齐且密度高
· 去掉账号,格子里只留中文名(账号移到 title 提示里,需要时悬停可看)
· 不设 max-height、不加 overflow —— 自然换行铺满,没有滚动条
· 组长:金色底 + 皇冠图标;移除按钮改成悬停才出现(避免误点)
· 无权限时方块不可点、也不出现移除按钮,纯展示

已通过 tsc 检查。
This commit is contained in:
2026-09-21 17:49:00 +08:00
parent 9598c3fb9f
commit 670436f68c

View File

@ -1,5 +1,5 @@
import { useState, useEffect, useCallback, useMemo } from "react";
import { Table, Button, Modal, Input, Checkbox, Tag, App, Spin, Empty, Select, Tooltip } from "antd";
import { Table, Button, Modal, Input, Checkbox, Tag, App, Spin, Empty, Select } from "antd";
import { Plus, Pencil, Trash2, UserPlus, Crown, ShieldCheck } from "lucide-react";
import { useAuth } from "../../contexts/AuthContext";
import { isSuperAdmin } from "../../constants/task";
@ -385,36 +385,47 @@ export default function AdminGroupsPage() {
) : detail.members.length === 0 ? (
<Empty description="该分组还没有成员" image={Empty.PRESENTED_IMAGE_SIMPLE} className="py-6" />
) : (
/* 标签云而非表格:成员多时一人一行要滚很久,标签能一行放好几个
有权限时:点标签正文切换组长、点 × 移除;无权限时纯展示。 */
<div className="flex flex-wrap gap-2 rounded-lg border border-gray-100 bg-gray-50/60 p-3">
/* 方块网格:每个成员一格,只显示中文名,全部铺开不做滚动
自动按容器宽度铺排auto-fill窗口越宽一行放得越多。
有权限时:点方块切换组长、悬停右上角出现移除;无权限时纯展示。 */
<div className="grid gap-2 [grid-template-columns:repeat(auto-fill,minmax(92px,1fr))]">
{detail.members.map((m) => (
<Tag
<div
key={m.user_id}
color={m.is_leader ? "gold" : undefined}
closable={detail.can_manage_members}
onClose={(e) => { e.preventDefault(); handleRemoveMember(m.user_id); }}
className="!m-0 !px-2.5 !py-1 !text-sm"
title={
detail.can_manage_members
? `${m.display_name}${m.user_id})· ${m.is_leader ? "点击取消组长" : "点击设为组长"}`
: `${m.display_name}${m.user_id}`
}
onClick={() => {
if (detail.can_manage_members) handleToggleLeader(m.user_id, !m.is_leader);
}}
className={`group relative flex h-11 select-none items-center justify-center rounded-lg border px-2 text-sm transition-colors ${
m.is_leader
? "border-amber-300 bg-amber-50 font-medium text-amber-800"
: "border-gray-200 bg-white text-gray-700"
} ${
detail.can_manage_members
? "cursor-pointer hover:border-blue-300 hover:bg-blue-50"
: ""
}`}
>
<Tooltip
title={
detail.can_manage_members
? (m.is_leader ? "点击取消组长" : "点击设为组长")
: undefined
}
>
<span
className={`select-none ${detail.can_manage_members ? "cursor-pointer" : ""}`}
onClick={() => {
if (detail.can_manage_members) handleToggleLeader(m.user_id, !m.is_leader);
}}
{m.is_leader && (
<Crown size={12} className="mr-1 shrink-0 text-amber-500" />
)}
<span className="truncate">{m.display_name}</span>
{/* 移除:默认藏起来,悬停该方块才出现,避免误点 */}
{detail.can_manage_members && (
<button
title="移出分组"
onClick={(e) => { e.stopPropagation(); handleRemoveMember(m.user_id); }}
className="absolute -right-1.5 -top-1.5 hidden h-4 w-4 items-center justify-center rounded-full bg-red-500 text-[10px] leading-none text-white hover:bg-red-600 group-hover:flex"
>
{m.is_leader && <Crown size={12} className="mr-1 inline align-[-1px]" />}
{m.display_name}
<span className="ml-1.5 font-mono text-xs opacity-50">{m.user_id}</span>
</span>
</Tooltip>
</Tag>
×
</button>
)}
</div>
))}
</div>
)}