import { useQuery } from '@tanstack/react-query'; import { Icon } from '@/app/Icon'; import { getGroupMembers, type GroupRole } from '@/lib/api/groups'; import { avatarBgClass, avatarLetter } from '@/lib/avatar'; import { useDebouncedValue } from '@/lib/hooks'; import { MENTION_ALL_SENTINEL, type PendingMention } from '@/lib/messages/mentions'; const ROLE_LABEL: Record = { owner: '群主', admin: '管理员', member: '' }; interface MentionPickerProps { topicId: string; query: string; onPick: (choice: PendingMention) => void; } /** * 设计稿 4.3:输入 `@` 触发的 260px 浮层。候选来自 `GET .../members?query=&mentionable=true` * (协议文档 1052/1735 行)-- 这一个响应同时带 `items`(已经是可提及成员,不用再拿全量列表自己过滤) * 和 `permissions.can_mention_all`,比向 ConversationView 另外要这两样数据都便宜。"所有人"是虚拟项, * 不对应真实成员,只在 `can_mention_all` 为真时出现在首位。 */ export function MentionPicker({ topicId, query, onPick }: MentionPickerProps) { const debouncedQuery = useDebouncedValue(query, 200); const membersQuery = useQuery({ queryKey: ['group-mentionable-members', topicId, debouncedQuery], queryFn: () => getGroupMembers(topicId, { query: debouncedQuery, mentionable: true }), }); const items = membersQuery.data?.items || []; const canMentionAll = !!membersQuery.data?.permissions?.can_mention_all; const showAll = canMentionAll && (!query || '所有人'.includes(query)); if (!showAll && items.length === 0 && !membersQuery.isLoading) return null; return (
{membersQuery.isLoading ? (
加载中…
) : ( <> {showAll ? ( ) : null} {items.map((m) => ( ))} )}
); }