From 25bd1df2908fabdad8cf443154cb4d29d2d73b2a Mon Sep 17 00:00:00 2001 From: nav Date: Tue, 12 May 2026 16:08:17 +0000 Subject: [PATCH] feat(frontend): add loading empty and error states for chat operations --- src/pages/ChatPage.tsx | 72 +++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/src/pages/ChatPage.tsx b/src/pages/ChatPage.tsx index afd8bc6..6c08d3a 100644 --- a/src/pages/ChatPage.tsx +++ b/src/pages/ChatPage.tsx @@ -26,6 +26,8 @@ export default function ChatPage() { const [socketState, setSocketState] = useState<'offline' | 'online'>('offline') const [onlineCount, setOnlineCount] = useState(0) const [typingUsers, setTypingUsers] = useState([]) + const [loading, setLoading] = useState(false) + const [error, setError] = useState('') const [seqFrom, setSeqFrom] = useState('1') const [seqTo, setSeqTo] = useState('999999') const [limit, setLimit] = useState('50') @@ -86,40 +88,63 @@ export default function ChatPage() { async function pullMessages() { if (!channelId) return - const res = await getApiClient().get(`/channels/${channelId}/messages`, { - params: { - seq_from: Number(seqFrom || '1'), - seq_to: Number(seqTo || '999999'), - limit: Number(limit || '50'), - }, - }) - setMessages(res.data.items ?? []) - setPageInfo(res.data.page ?? null) + setLoading(true) + setError('') + try { + const res = await getApiClient().get(`/channels/${channelId}/messages`, { + params: { + seq_from: Number(seqFrom || '1'), + seq_to: Number(seqTo || '999999'), + limit: Number(limit || '50'), + }, + }) + setMessages(res.data.items ?? []) + setPageInfo(res.data.page ?? null) + } catch { + setError('消息拉取失败') + } finally { + setLoading(false) + } } async function sendMessage() { if (!channelId || !content.trim()) return - await getApiClient().post(`/channels/${channelId}/messages`, { - content, - authorUserId: 'frontend-user', - }) - socket.emit('typing.stop', { channelId }) - setContent('') + setError('') + try { + await getApiClient().post(`/channels/${channelId}/messages`, { + content, + authorUserId: 'frontend-user', + }) + socket.emit('typing.stop', { channelId }) + setContent('') + } catch { + setError('发送失败') + } } async function editMessage() { if (!channelId || !editingMessageId || !editingContent.trim()) return - await getApiClient().patch(`/channels/${channelId}/messages/${editingMessageId}`, { - content: editingContent, - }) - setEditingContent('') - await pullMessages() + setError('') + try { + await getApiClient().patch(`/channels/${channelId}/messages/${editingMessageId}`, { + content: editingContent, + }) + setEditingContent('') + await pullMessages() + } catch { + setError('编辑失败') + } } async function deleteMessage(messageId: string) { if (!channelId || !messageId) return - await getApiClient().delete(`/channels/${channelId}/messages/${messageId}`) - await pullMessages() + setError('') + try { + await getApiClient().delete(`/channels/${channelId}/messages/${messageId}`) + await pullMessages() + } catch { + setError('删除失败') + } } function onChangeChannel(value: string) { @@ -155,6 +180,8 @@ export default function ChatPage() {

Guild: {guildId || '-'}

Socket: {socketState}

在线人数: {onlineCount}

+ {loading ?

加载中...

: null} + {error ?

{error}

: null} {typingUsers.length ?

正在输入: {typingUsers.join(', ')}

: null}
onChangeChannel(e.target.value)} placeholder="Channel ID" /> @@ -186,6 +213,7 @@ export default function ChatPage() { ))} + {!loading && !messages.length ?

暂无消息

: null} {pageInfo ? (

next_expected_seq: {pageInfo.nextExpectedSeq ?? '-'} | highest_committed_seq:{' '}