fix(chat): show group member count loading and failed states

This commit is contained in:
tisonhuang
2026-03-04 18:40:53 +08:00
parent 924ff1b6fc
commit 1652ebc4ad
2 changed files with 69 additions and 10 deletions

View File

@@ -3026,6 +3026,16 @@
font-size: 12px; font-size: 12px;
font-weight: 600; font-weight: 600;
color: var(--text-secondary); color: var(--text-secondary);
&.loading {
color: var(--text-tertiary);
font-weight: 500;
}
&.failed {
color: #b45309;
font-weight: 600;
}
} }
} }

View File

@@ -260,6 +260,8 @@ interface SessionExportCacheMeta {
source: 'memory' | 'disk' | 'fresh' source: 'memory' | 'disk' | 'fresh'
} }
type GroupMessageCountStatus = 'loading' | 'ready' | 'failed'
interface GroupPanelMember { interface GroupPanelMember {
username: string username: string
displayName: string displayName: string
@@ -271,6 +273,7 @@ interface GroupPanelMember {
isOwner?: boolean isOwner?: boolean
isFriend: boolean isFriend: boolean
messageCount: number messageCount: number
messageCountStatus: GroupMessageCountStatus
} }
interface SessionListCachePayload { interface SessionListCachePayload {
@@ -1131,7 +1134,10 @@ function ChatPage(props: ChatPageProps) {
} }
}, [applySessionDetailStats, currentSessionId, isLoadingRelationStats]) }, [applySessionDetailStats, currentSessionId, isLoadingRelationStats])
const normalizeGroupPanelMembers = useCallback((payload: GroupPanelMember[]): GroupPanelMember[] => { const normalizeGroupPanelMembers = useCallback((
payload: GroupPanelMember[],
options?: { messageCountStatus?: GroupMessageCountStatus }
): GroupPanelMember[] => {
const membersPayload = Array.isArray(payload) ? payload : [] const membersPayload = Array.isArray(payload) ? payload : []
return membersPayload return membersPayload
.map((member: GroupPanelMember): GroupPanelMember | null => { .map((member: GroupPanelMember): GroupPanelMember | null => {
@@ -1144,6 +1150,9 @@ function ChatPage(props: ChatPageProps) {
member.nickname || member.nickname ||
username username
) )
const rawStatus = member.messageCountStatus
const normalizedStatus: GroupMessageCountStatus = options?.messageCountStatus
?? (rawStatus === 'loading' || rawStatus === 'failed' ? rawStatus : 'ready')
return { return {
username, username,
@@ -1155,7 +1164,8 @@ function ChatPage(props: ChatPageProps) {
groupNickname: member.groupNickname, groupNickname: member.groupNickname,
isOwner: Boolean(member.isOwner), isOwner: Boolean(member.isOwner),
isFriend: Boolean(member.isFriend), isFriend: Boolean(member.isFriend),
messageCount: Number.isFinite(member.messageCount) ? Math.max(0, Math.floor(member.messageCount)) : 0 messageCount: Number.isFinite(member.messageCount) ? Math.max(0, Math.floor(member.messageCount)) : 0,
messageCountStatus: normalizedStatus
} }
}) })
.filter((member: GroupPanelMember | null): member is GroupPanelMember => Boolean(member)) .filter((member: GroupPanelMember | null): member is GroupPanelMember => Boolean(member))
@@ -1166,7 +1176,8 @@ function ChatPage(props: ChatPageProps) {
const friendDiff = Number(b.isFriend) - Number(a.isFriend) const friendDiff = Number(b.isFriend) - Number(a.isFriend)
if (friendDiff !== 0) return friendDiff if (friendDiff !== 0) return friendDiff
if (a.messageCount !== b.messageCount) return b.messageCount - a.messageCount const canSortByCount = a.messageCountStatus === 'ready' && b.messageCountStatus === 'ready'
if (canSortByCount && a.messageCount !== b.messageCount) return b.messageCount - a.messageCount
return a.displayName.localeCompare(b.displayName, 'zh-Hans-CN') return a.displayName.localeCompare(b.displayName, 'zh-Hans-CN')
}) })
}, []) }, [])
@@ -1241,6 +1252,21 @@ function ChatPage(props: ChatPageProps) {
} }
}, []) }, [])
const setGroupMembersCountStatus = useCallback((
status: GroupMessageCountStatus,
options?: { onlyWhenNotReady?: boolean }
) => {
setGroupPanelMembers((prev) => {
if (!Array.isArray(prev) || prev.length === 0) return prev
if (options?.onlyWhenNotReady && prev.some((member) => member.messageCountStatus === 'ready')) {
return prev
}
const next = normalizeGroupPanelMembers(prev, { messageCountStatus: status })
const changed = next.some((member, index) => member.messageCountStatus !== prev[index]?.messageCountStatus)
return changed ? next : prev
})
}, [normalizeGroupPanelMembers])
const syncGroupMembersMyCountFromDetail = useCallback((chatroomId: string, myMessageCount: number) => { const syncGroupMembersMyCountFromDetail = useCallback((chatroomId: string, myMessageCount: number) => {
if (!chatroomId || !chatroomId.includes('@chatroom')) return if (!chatroomId || !chatroomId.includes('@chatroom')) return
const normalizedCount = Number.isFinite(myMessageCount) ? Math.max(0, Math.floor(myMessageCount)) : 0 const normalizedCount = Number.isFinite(myMessageCount) ? Math.max(0, Math.floor(myMessageCount)) : 0
@@ -1319,6 +1345,7 @@ function ChatPage(props: ChatPageProps) {
const refreshMessageCountsInBackground = (forceRefresh: boolean) => { const refreshMessageCountsInBackground = (forceRefresh: boolean) => {
startedBackgroundRefresh = true startedBackgroundRefresh = true
setIsRefreshingGroupMembers(true) setIsRefreshingGroupMembers(true)
setGroupMembersCountStatus('loading', { onlyWhenNotReady: true })
void (async () => { void (async () => {
try { try {
const countsResult = await getGroupMembersPanelDataWithTimeout( const countsResult = await getGroupMembersPanelDataWithTimeout(
@@ -1329,10 +1356,14 @@ function ChatPage(props: ChatPageProps) {
if (requestSeq !== groupMembersRequestSeqRef.current) return if (requestSeq !== groupMembersRequestSeqRef.current) return
if (!countsResult.success || !Array.isArray(countsResult.data)) { if (!countsResult.success || !Array.isArray(countsResult.data)) {
setGroupMembersError('成员列表已加载,发言统计稍后再试') setGroupMembersError('成员列表已加载,发言统计稍后再试')
setGroupMembersCountStatus('failed', { onlyWhenNotReady: true })
return return
} }
const membersWithCounts = normalizeGroupPanelMembers(countsResult.data as GroupPanelMember[]) const membersWithCounts = normalizeGroupPanelMembers(
countsResult.data as GroupPanelMember[],
{ messageCountStatus: 'ready' }
)
setGroupPanelMembers(membersWithCounts) setGroupPanelMembers(membersWithCounts)
syncGroupMyMessagesFromMembers(chatroomId, membersWithCounts) syncGroupMyMessagesFromMembers(chatroomId, membersWithCounts)
setGroupMembersError(null) setGroupMembersError(null)
@@ -1341,6 +1372,7 @@ function ChatPage(props: ChatPageProps) {
} catch { } catch {
if (requestSeq !== groupMembersRequestSeqRef.current) return if (requestSeq !== groupMembersRequestSeqRef.current) return
setGroupMembersError('成员列表已加载,发言统计稍后再试') setGroupMembersError('成员列表已加载,发言统计稍后再试')
setGroupMembersCountStatus('failed', { onlyWhenNotReady: true })
} finally { } finally {
if (requestSeq === groupMembersRequestSeqRef.current) { if (requestSeq === groupMembersRequestSeqRef.current) {
setIsRefreshingGroupMembers(false) setIsRefreshingGroupMembers(false)
@@ -1350,9 +1382,13 @@ function ChatPage(props: ChatPageProps) {
} }
if (cacheFresh && cached) { if (cacheFresh && cached) {
setGroupPanelMembers(cached.members) const cachedMembers = normalizeGroupPanelMembers(
cached.members,
{ messageCountStatus: cached.includeMessageCounts ? 'ready' : 'loading' }
)
setGroupPanelMembers(cachedMembers)
if (cached.includeMessageCounts) { if (cached.includeMessageCounts) {
syncGroupMyMessagesFromMembers(chatroomId, cached.members) syncGroupMyMessagesFromMembers(chatroomId, cachedMembers)
} }
setGroupMembersError(null) setGroupMembersError(null)
setGroupMembersLoadingHint('') setGroupMembersLoadingHint('')
@@ -1368,9 +1404,13 @@ function ChatPage(props: ChatPageProps) {
setGroupMembersError(null) setGroupMembersError(null)
if (hasCachedMembers && cached) { if (hasCachedMembers && cached) {
setGroupPanelMembers(cached.members) const cachedMembers = normalizeGroupPanelMembers(
cached.members,
{ messageCountStatus: cached.includeMessageCounts ? 'ready' : 'loading' }
)
setGroupPanelMembers(cachedMembers)
if (cached.includeMessageCounts) { if (cached.includeMessageCounts) {
syncGroupMyMessagesFromMembers(chatroomId, cached.members) syncGroupMyMessagesFromMembers(chatroomId, cachedMembers)
} }
setIsRefreshingGroupMembers(true) setIsRefreshingGroupMembers(true)
setGroupMembersLoadingHint('') setGroupMembersLoadingHint('')
@@ -1402,7 +1442,10 @@ function ChatPage(props: ChatPageProps) {
return return
} }
const members = normalizeGroupPanelMembers(membersResult.data as GroupPanelMember[]) const members = normalizeGroupPanelMembers(
membersResult.data as GroupPanelMember[],
{ messageCountStatus: 'loading' }
)
setGroupPanelMembers(members) setGroupPanelMembers(members)
setGroupMembersError(null) setGroupMembersError(null)
updateGroupMembersPanelCache(chatroomId, members, false) updateGroupMembersPanelCache(chatroomId, members, false)
@@ -3831,7 +3874,13 @@ function ChatPage(props: ChatPageProps) {
</span> </span>
</div> </div>
</div> </div>
<span className="group-member-count">{member.messageCount.toLocaleString()} </span> <span className={`group-member-count ${member.messageCountStatus}`}>
{member.messageCountStatus === 'loading'
? '统计中'
: member.messageCountStatus === 'failed'
? '统计失败'
: `${member.messageCount.toLocaleString()}`}
</span>
</div> </div>
))} ))}
</div> </div>