diff --git a/shared/cache/useCache.ts b/shared/cache/useCache.ts index f515ab61..373235ad 100644 --- a/shared/cache/useCache.ts +++ b/shared/cache/useCache.ts @@ -34,8 +34,11 @@ export function useCachedUserInfo( /** * 用户登录状态 */ -export function useCachedOnlineStatus(ids: string[]): boolean[] { - const { data } = useQuery( +export function useCachedOnlineStatus( + ids: string[], + onOnlineStatusUpdate?: (onlineStatus: boolean[]) => void +): boolean[] { + const { data, isSuccess } = useQuery( ['onlineStatus', ids.join(',')], () => getUserOnlineStatus(ids), { @@ -43,5 +46,11 @@ export function useCachedOnlineStatus(ids: string[]): boolean[] { } ); + if (isSuccess && Array.isArray(data)) { + if (typeof onOnlineStatusUpdate === 'function' && data) { + onOnlineStatusUpdate(data); + } + } + return data ?? ids.map(() => false); } diff --git a/shared/i18n/langs/en-US/translation.json b/shared/i18n/langs/en-US/translation.json index 9a9c9ed0..f0e0e8c7 100644 --- a/shared/i18n/langs/en-US/translation.json +++ b/shared/i18n/langs/en-US/translation.json @@ -28,6 +28,7 @@ "k24ccd723": "Refresh now", "k267cc491": "Me", "k2a8031e": "Homepage", + "k2c6ee8d": "Confirm the action", "k2c7df74f": "Modify Group Panel", "k2d6cfb27": "Chat Channel", "k2ec4966c": "Selected {{num}} items", @@ -219,6 +220,7 @@ "kdf6e53ca": "Converse does not have permission", "ke17b2c87": "Do not upload pictures that violate local laws and regulations", "ke187440d": "Panel type cannot be empty", + "kea977d95": "The following users are offline", "kecb51e2c": "Old password", "kecbd7449": "Delete", "ked2baf28": "Loading...", diff --git a/shared/i18n/langs/zh-CN/translation.json b/shared/i18n/langs/zh-CN/translation.json index 0c499c6c..c73224d3 100644 --- a/shared/i18n/langs/zh-CN/translation.json +++ b/shared/i18n/langs/zh-CN/translation.json @@ -28,6 +28,7 @@ "k24ccd723": "立即刷新", "k267cc491": "我", "k2a8031e": "个人主页", + "k2c6ee8d": "确认操作", "k2c7df74f": "编辑群组面板", "k2d6cfb27": "聊天频道", "k2ec4966c": "已选择 {{num}} 项", @@ -219,6 +220,7 @@ "kdf6e53ca": "会话没有权限", "ke17b2c87": "请勿上传违反当地法律法规的图片", "ke187440d": "面板类型不能为空", + "kea977d95": "以下用户已离线", "kecb51e2c": "旧密码", "kecbd7449": "删除", "ked2baf28": "加载中...", diff --git a/shared/model/user.ts b/shared/model/user.ts index 3d690673..cd774f50 100644 --- a/shared/model/user.ts +++ b/shared/model/user.ts @@ -197,12 +197,10 @@ export async function fetchUserInfo(userId: string): Promise { export async function getUserOnlineStatus( userIds: string[] ): Promise { - const { data } = await request.get( + const { data } = await request.post( '/api/gateway/checkUserOnline', { - params: { - userIds, - }, + userIds, } ); diff --git a/web/src/components/Panel/group/MembersPanel.tsx b/web/src/components/Panel/group/MembersPanel.tsx index 172b85eb..c3f27c1e 100644 --- a/web/src/components/Panel/group/MembersPanel.tsx +++ b/web/src/components/Panel/group/MembersPanel.tsx @@ -1,8 +1,13 @@ import { Icon } from '@/components/Icon'; import { UserListItem } from '@/components/UserListItem'; -import { Input, Skeleton } from 'antd'; +import { Divider, Input, Skeleton } from 'antd'; import React, { useMemo, useState } from 'react'; -import { t, useGroupInfo } from 'tailchat-shared'; +import { + t, + useCachedOnlineStatus, + useGroupInfo, + UserBaseInfo, +} from 'tailchat-shared'; import { useUserInfoList } from 'tailchat-shared/hooks/model/useUserInfoList'; interface MembersPanelProps { @@ -17,6 +22,27 @@ export const MembersPanel: React.FC = React.memo((props) => { const members = groupInfo?.members ?? []; const userInfoList = useUserInfoList(members.map((m) => m.userId)); const [searchStr, setSearchStr] = useState(''); + const membersOnlineStatus = useCachedOnlineStatus( + members.map((m) => m.userId) + ); + + const groupedMembers = useMemo(() => { + const online: UserBaseInfo[] = []; + const offline: UserBaseInfo[] = []; + + userInfoList.forEach((m, i) => { + if (membersOnlineStatus[i] === true) { + online.push(m); + } else { + offline.push(m); + } + }); + + return { + online, + offline, + }; + }, [userInfoList, membersOnlineStatus]); const filteredGroupMembers = useMemo(() => { return userInfoList.filter((u) => u.nickname.includes(searchStr)); @@ -26,6 +52,12 @@ export const MembersPanel: React.FC = React.memo((props) => { return ; } + const isSearching = searchStr !== ''; + + const renderUser = (member: UserBaseInfo) => ( + + ); + return (
@@ -37,9 +69,17 @@ export const MembersPanel: React.FC = React.memo((props) => { />
- {filteredGroupMembers.map((member) => ( - - ))} + {isSearching ? ( + filteredGroupMembers.map(renderUser) + ) : ( + <> + {groupedMembers.online.map(renderUser)} + + {t('以下用户已离线')} + + {groupedMembers.offline.map(renderUser)} + + )}
); });