优化消息内容的换行显示,解决间距过大的问题
parent
5f947b4d64
commit
9c208cd8e1
|
|
@ -1,8 +1,10 @@
|
|||
import { Button, Dropdown, Space, Tag, Tooltip, Avatar } from 'antd';
|
||||
import { useMemo } from 'react';
|
||||
import { CopyOutlined, SyncOutlined } from '@ant-design/icons';
|
||||
import type { BranchInfo, ChatMessage } from '../../../../api';
|
||||
import type { Agent } from '../../../../api/agents';
|
||||
import Markdown from '../../../../components/Markdown';
|
||||
import { formatMessageContent } from '../../utils/format';
|
||||
import type { CopyMode } from '../../utils/copy';
|
||||
import { ReasoningView, RetrievedView, ToolCallView } from './MetaViews';
|
||||
import './MessageItem.css';
|
||||
|
|
@ -21,6 +23,8 @@ export default function MessageItem(props: {
|
|||
}) {
|
||||
const { message, agentList, currentAgentId, highlighted, branch, busy, onRegenerate, onSwitchBranch, onCopy, isMobile } = props;
|
||||
|
||||
const formattedContent = useMemo(() => formatMessageContent(message.content), [message.content]);
|
||||
|
||||
const speakerType = (message as any)?.speaker?.type as ('user' | 'agent' | undefined);
|
||||
const speakerId = (message as any)?.speaker?.id as string | undefined;
|
||||
const isUser = speakerType ? speakerType === 'user' : message.role === 'user';
|
||||
|
|
@ -66,7 +70,7 @@ export default function MessageItem(props: {
|
|||
</span>
|
||||
</div>
|
||||
<div className={`bubble ${bubbleRole}`}>
|
||||
<Markdown>{message.content}</Markdown>
|
||||
<Markdown>{formattedContent}</Markdown>
|
||||
<div className="message-item-actions">
|
||||
{hasBranches && (
|
||||
<Space size={2}>
|
||||
|
|
@ -86,8 +90,8 @@ export default function MessageItem(props: {
|
|||
trigger={['click']}
|
||||
menu={{
|
||||
items: [
|
||||
{ key: 'plain', label: '复制纯文本', onClick: () => onCopy?.(message.content, 'plain') },
|
||||
{ key: 'markdown', label: '复制 Markdown', onClick: () => onCopy?.(message.content, 'markdown') }
|
||||
{ key: 'plain', label: '复制纯文本', onClick: () => onCopy?.(formattedContent, 'plain') },
|
||||
{ key: 'markdown', label: '复制 Markdown', onClick: () => onCopy?.(formattedContent, 'markdown') }
|
||||
]
|
||||
}}
|
||||
>
|
||||
|
|
@ -113,11 +117,11 @@ export default function MessageItem(props: {
|
|||
<div className="message-item-user">
|
||||
<div className="message-item-user-content-wrapper">
|
||||
<div className={`bubble ${bubbleRole}`}>
|
||||
{message.content.includes(' ? (
|
||||
<Markdown>{message.content}</Markdown>
|
||||
{formattedContent.includes(' ? (
|
||||
<Markdown>{formattedContent}</Markdown>
|
||||
) : (
|
||||
<span dangerouslySetInnerHTML={{
|
||||
__html: message.content.replace(/@([^\s]+)/g, '<span class="mention">@$1</span>')
|
||||
__html: formattedContent.replace(/@([^\s]+)/g, '<span class="mention">@$1</span>')
|
||||
}} />
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* 清理消息内容中的冗余换行
|
||||
* 1. 将 3 个及以上的换行替换为 2 个换行
|
||||
* 2. 将特定的 Markdown 块元素前后的双换行替换为单换行,以减少间距
|
||||
*/
|
||||
export function formatMessageContent(content: string): string {
|
||||
if (!content) return '';
|
||||
|
||||
return content
|
||||
// 将 3 个及以上的换行替换为 2 个
|
||||
.replace(/\n{3,}/g, '\n\n')
|
||||
// 针对 Markdown 块元素,将双换行缩小为单换行
|
||||
// 匹配 \n\n 后面跟着 #, -, *, >, --- 等
|
||||
.replace(/\n\n(?=[#\-*>]|---)/g, '\n')
|
||||
// 匹配 #, -, *, >, --- 后面跟着 \n\n
|
||||
// 由于 JavaScript 不支持所有环境下的 lookbehind,我们先处理上面的
|
||||
.replace(/([#\-*>]|---)\n\n/g, '$1\n');
|
||||
}
|
||||
|
|
@ -751,7 +751,7 @@ body {
|
|||
}
|
||||
|
||||
.chat-body .messages-container {
|
||||
max-width: 780px;
|
||||
max-width: 1080px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 16px 12px 80px;
|
||||
|
|
@ -785,6 +785,7 @@ body {
|
|||
border: 0;
|
||||
border-bottom-left-radius: 5px;
|
||||
box-shadow: none;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.bubble.assistant p {
|
||||
|
|
|
|||
Loading…
Reference in New Issue