fix: 按 speaker.type 区分消息左右与头像,并改为 iMessage 气泡样式
parent
b1df40e983
commit
e6116c1c80
|
|
@ -15,7 +15,11 @@ export interface ToolCallTrace {
|
|||
|
||||
export interface ChatMessage {
|
||||
id: string;
|
||||
role: 'user' | 'assistant';
|
||||
role: 'user' | 'assistant' | 'agent' | 'system';
|
||||
speaker?: {
|
||||
id: string;
|
||||
type: 'user' | 'agent';
|
||||
};
|
||||
content: string;
|
||||
reasoning?: string | null;
|
||||
parentId?: string | null;
|
||||
|
|
@ -73,4 +77,3 @@ export const ChatAttachmentsAPI = {
|
|||
return api.post<{ files: ChatAttachment[] }>('/chat/attachments', fd).then((r) => r.data);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ export default function ChatBody(props: {
|
|||
agentList={agentList}
|
||||
currentAgentId={currentAgentId}
|
||||
highlighted={highlightId === m.id}
|
||||
branch={m.role === 'assistant' && m.parentId ? branches[m.parentId] : undefined}
|
||||
branch={((m as any)?.speaker?.type ? (m as any).speaker.type === 'agent' : m.role === 'assistant') && m.parentId ? branches[m.parentId] : undefined}
|
||||
busy={sending}
|
||||
onRegenerate={onRegenerate}
|
||||
onSwitchBranch={onSwitchBranch}
|
||||
|
|
@ -76,7 +76,9 @@ export default function ChatBody(props: {
|
|||
const streamingAgent = agentList.find(a => a.id === streamingAgentId);
|
||||
if (streamingAgent) {
|
||||
return (
|
||||
<Avatar src={streamingAgent.avatar} size={36} style={{ flexShrink: 0, marginTop: 2 }} />
|
||||
<Avatar src={streamingAgent.avatar} size={36} style={{ flexShrink: 0, marginTop: 2, backgroundColor: '#52c41a' }}>
|
||||
{streamingAgent.name?.charAt(0)?.toUpperCase() || 'A'}
|
||||
</Avatar>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ function summarize(content: string) {
|
|||
|
||||
export default function ChatOutline(props: { messages: ChatMessage[]; onJump: (id: string) => void; activeId?: string | null }) {
|
||||
const { messages, onJump, activeId } = props;
|
||||
const items = messages.filter((m) => m.role === 'assistant');
|
||||
const items = messages.filter((m) => ((m as any)?.speaker?.type ? (m as any).speaker.type === 'agent' : m.role === 'assistant'));
|
||||
|
||||
if (items.length === 0) return null;
|
||||
|
||||
|
|
@ -38,4 +38,3 @@ export default function ChatOutline(props: { messages: ChatMessage[]; onJump: (i
|
|||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,12 @@ export default function MessageItem(props: {
|
|||
}) {
|
||||
const { message, agentList, currentAgentId, highlighted, branch, busy, onRegenerate, onSwitchBranch, onCopy } = props;
|
||||
|
||||
const speakerType = (message as any)?.speaker?.type as ('user' | 'agent' | undefined);
|
||||
const isUser = speakerType ? speakerType === 'user' : message.role === 'user';
|
||||
const bubbleRole = isUser ? 'user' : 'assistant';
|
||||
|
||||
// 获取回答者 Agent 信息
|
||||
const answerAgentId = message.agent_id || (message.role === 'assistant' ? currentAgentId : undefined);
|
||||
const answerAgentId = message.agent_id || (!isUser ? currentAgentId : undefined);
|
||||
const answerAgent = answerAgentId ? agentList.find(a => a.id === answerAgentId) : undefined;
|
||||
const hasBranches = !!branch && branch.total > 1;
|
||||
const activeIdx = branch?.activeIndex ?? 0;
|
||||
|
|
@ -49,9 +53,8 @@ export default function MessageItem(props: {
|
|||
transition: 'background 0.4s, padding 0.4s'
|
||||
}}
|
||||
>
|
||||
{message.role === 'assistant' ? (
|
||||
{!isUser ? (
|
||||
<div style={{ display: 'flex', gap: 12, alignItems: 'flex-start' }}>
|
||||
{/* AGENT: 头像在左侧,内容在右侧(靠左对齐) */}
|
||||
<Avatar
|
||||
src={answerAgent?.avatar}
|
||||
size={36}
|
||||
|
|
@ -74,7 +77,7 @@ export default function MessageItem(props: {
|
|||
{answerAgent?.name || 'AI'}
|
||||
</span>
|
||||
</div>
|
||||
<div className={`bubble ${message.role}`}>
|
||||
<div className={`bubble ${bubbleRole}`}>
|
||||
<Markdown>{message.content}</Markdown>
|
||||
</div>
|
||||
<div className="monica-msg-actions">
|
||||
|
|
@ -124,8 +127,7 @@ export default function MessageItem(props: {
|
|||
</div>
|
||||
) : (
|
||||
<div style={{ display: 'flex', gap: 12, alignItems: 'flex-start', justifyContent: 'flex-end' }}>
|
||||
{/* 用户: 头像在右侧,内容在左侧(靠右对齐) */}
|
||||
<div style={{ maxWidth: '78%', display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
|
||||
<div style={{ flex: 1, minWidth: 0, maxWidth: '78%', display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}>
|
||||
<div style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
|
@ -140,7 +142,7 @@ export default function MessageItem(props: {
|
|||
我
|
||||
</span>
|
||||
</div>
|
||||
<div className={`bubble ${message.role}`}>
|
||||
<div className={`bubble ${bubbleRole}`}>
|
||||
{message.content.includes(' ? (
|
||||
<Markdown>{message.content}</Markdown>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -628,6 +628,7 @@ body {
|
|||
|
||||
.bubble {
|
||||
max-width: 78%;
|
||||
display: inline-block;
|
||||
padding: 14px 18px;
|
||||
border-radius: 14px;
|
||||
margin-bottom: 14px;
|
||||
|
|
@ -638,18 +639,18 @@ body {
|
|||
}
|
||||
|
||||
.bubble.user {
|
||||
background: var(--color-brand-soft);
|
||||
color: var(--color-text);
|
||||
background: #0a84ff;
|
||||
color: #ffffff;
|
||||
margin-left: auto;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
|
||||
.bubble.assistant {
|
||||
background: #ffffff;
|
||||
color: var(--color-text);
|
||||
border: 1px solid var(--color-border);
|
||||
background: #e9e9eb;
|
||||
color: #111827;
|
||||
border: 0;
|
||||
border-bottom-left-radius: 5px;
|
||||
box-shadow: var(--shadow-xs);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.bubble.assistant p {
|
||||
|
|
|
|||
Loading…
Reference in New Issue