feat(chat): port chat widget components from Dart to React

This commit is contained in:
2026-06-09 20:19:52 +08:00
parent 199a14650e
commit 109a3e3855
48 changed files with 2463 additions and 382 deletions
@@ -0,0 +1,49 @@
"use client";
/**
* MessageBubble 消息气泡(容器)
*
* 原始 Dart: lib/ui/chat/widgets/message_bubble.dart52 行)
*
* 组成(从左到右):
* - AI[Avatar] [Content] [占位 spacer]
* - 用户:[占位 spacer] [Content] [Avatar]
*/
import { useUserState } from "@/stores/user/user-context";
import { MessageAvatar } from "./message-avatar";
import { MessageContent } from "./message-content";
import styles from "./chat-area.module.css";
export interface MessageBubbleProps {
content: string;
imageUrl?: string | null;
isFromAI: boolean;
}
export function MessageBubble({ content, imageUrl, isFromAI }: MessageBubbleProps) {
const { avatarUrl } = useUserState();
if (isFromAI) {
return (
<div className={styles.bubbleRowAi} aria-label="AI message">
<MessageAvatar isFromAI={true} />
<div style={{ width: 8 }} />
<MessageContent
content={content}
imageUrl={imageUrl}
isFromAI={true}
/>
<div style={{ width: 43 }} /> {/* 占位:保持与头像宽度一致 */}
</div>
);
}
return (
<div className={styles.bubbleRowUser} aria-label="User message">
<div style={{ width: 43 }} /> {/* 占位 */}
<MessageContent content={content} imageUrl={imageUrl} isFromAI={false} />
<div style={{ width: 8 }} />
<MessageAvatar isFromAI={false} userAvatarUrl={avatarUrl} />
</div>
);
}