diff --git a/web/src/features/messages/MentionPicker.tsx b/web/src/features/messages/MentionPicker.tsx index 3e6b8e5b..c1a2983e 100644 --- a/web/src/features/messages/MentionPicker.tsx +++ b/web/src/features/messages/MentionPicker.tsx @@ -50,28 +50,38 @@ export function MentionPicker({ topicId, query, onPick }: MentionPickerProps) { 所有人 ) : null} - {items.map((m) => ( - - ))} + {label} + {m.role !== 'member' ? ( + + {ROLE_LABEL[m.role]} + + ) : null} + + ); + })} )} diff --git a/web/src/lib/api/groups.ts b/web/src/lib/api/groups.ts index d3dd340b..04d8e4f7 100644 --- a/web/src/lib/api/groups.ts +++ b/web/src/lib/api/groups.ts @@ -147,7 +147,23 @@ export type GroupRole = 'owner' | 'admin' | 'member'; export interface GroupMember { user_id: string; + /** + * Real, live-confirmed gotcha (2026-09-24): this is NOT always the member's own real name. + * Reading server/im_http.go's userSummaryPayload confirms `display_name` here unconditionally + * prefers the CALLING viewer's own private remark for that member when one is set, falling back + * to their real public nickname only when the viewer has no remark for them -- correct and + * intended for rendering a list to yourself (README's member list/search), completely wrong for + * anything that gets baked into shared message CONTENT once and read by everyone from then on + * (an @mention's label): a real reported bug was exactly this -- a group owner's own private + * remark for a member ("小号1") ended up as that member's permanent @mention text, which every + * OTHER member then saw with no idea who it meant. Use `nickname` (below) instead for that case. + */ display_name?: string; + /** The member's own real public profile nickname -- same backend response, but from + * copyUserNickname(), which reads straight off their public profile and is NEVER shadowed by the + * viewer's own remark the way `display_name` above is. This is what stays correct for everyone + * once baked into shared content (an @mention's label), not just for the viewer's own screen. */ + nickname?: string; avatar_file_id?: string; role: GroupRole; mentionable?: boolean;