优化消息内容的换行显示,解决间距过大的问题

main
sp mac bookpro 2605 2026-07-22 17:44:20 +08:00
parent 5f947b4d64
commit 9c208cd8e1
3 changed files with 30 additions and 7 deletions

View File

@ -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('![image](') ? (
<Markdown>{message.content}</Markdown>
{formattedContent.includes('![image](') ? (
<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>

View File

@ -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');
}

View File

@ -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 {