59 lines
2.0 KiB
Plaintext
59 lines
2.0 KiB
Plaintext
|
|
---
|
|||
|
|
title: 消息线程
|
|||
|
|
description: 组合滚动容器、消息布局与气泡,同时保护用户阅读历史消息的位置。
|
|||
|
|
order: 32
|
|||
|
|
toc:
|
|||
|
|
- id: structure
|
|||
|
|
title: 组件结构
|
|||
|
|
- id: messages
|
|||
|
|
title: 渲染消息
|
|||
|
|
- id: ownership
|
|||
|
|
title: 状态归属
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 组件结构 {#structure}
|
|||
|
|
|
|||
|
|
```tsx
|
|||
|
|
import {
|
|||
|
|
MessageScroller,
|
|||
|
|
MessageScrollerButton,
|
|||
|
|
MessageScrollerContent,
|
|||
|
|
MessageScrollerItem,
|
|||
|
|
MessageScrollerProvider,
|
|||
|
|
MessageScrollerViewport,
|
|||
|
|
} from "@workspace/ui/components/message-scroller"
|
|||
|
|
|
|||
|
|
export function Thread({ messages }: { messages: ChatMessage[] }) {
|
|||
|
|
return (
|
|||
|
|
<MessageScrollerProvider>
|
|||
|
|
<MessageScroller className="h-[32rem]">
|
|||
|
|
<MessageScrollerViewport>
|
|||
|
|
<MessageScrollerContent className="gap-5 p-4">
|
|||
|
|
{messages.map((message, index) => (
|
|||
|
|
<MessageScrollerItem
|
|||
|
|
key={message.id}
|
|||
|
|
messageId={message.id}
|
|||
|
|
scrollAnchor={index === messages.length - 1}
|
|||
|
|
>
|
|||
|
|
<ChatMessageRow message={message} />
|
|||
|
|
</MessageScrollerItem>
|
|||
|
|
))}
|
|||
|
|
</MessageScrollerContent>
|
|||
|
|
</MessageScrollerViewport>
|
|||
|
|
<MessageScrollerButton />
|
|||
|
|
</MessageScroller>
|
|||
|
|
</MessageScrollerProvider>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 渲染消息 {#messages}
|
|||
|
|
|
|||
|
|
在 `ChatMessageRow` 中使用 `Message`、`MessageAvatar`、`MessageContent`、`MessageHeader` 和 `MessageFooter` 表达参与者结构,再在 Content 内组合一个或多个 `Bubble`。发送者消息可使用 `align="end"`,但不要根据文本语言交换消息归属。
|
|||
|
|
|
|||
|
|
附件放入相同的 `MessageContent`。如果一条消息没有气泡背景,使用 `Bubble variant="ghost"`,Header 与 Footer 会自动移除气泡对应的水平 padding。
|
|||
|
|
|
|||
|
|
## 状态归属 {#ownership}
|
|||
|
|
|
|||
|
|
`MessageScroller` 管理跟随底部、可见性与跳转按钮;应用管理消息数组、分页、加载、已读和重试。加载更早消息时应保持稳定 ID,并使用 scroller API 维持视觉锚点,而不是在组件内复制一套滚动监听。
|