Commit 80e91beb by Liu

fix:流式换行处理

parent 4780fa33
......@@ -8,6 +8,7 @@ import { processApiResponse } from './helper'
import { ChatWelcome } from './components/ChatWelcome'
import { ChatItemUser } from './components/ChatItem/ChatItemUser'
import { ChatAnswerBox } from './components/ChatItem/ChatAnswerBox'
import { trimSpacesOnly } from './components/ChatItem/markdownFormatter'
import { ChatEditor } from '@/components/ChatEditor'
import type { ChatRecord } from '@/types/chat'
import { fetchUserQaRecordPage } from '@/api/conversation'
......@@ -162,9 +163,11 @@ export const Chat: React.FC = () => {
// 创建最后一项的新对象,合并现有数据和新的 answer
const originalAnswer = (newItems[lastIndex].answerList?.[0]?.answer || '') + msg.content.data.answer
// 移除所有括号及其内容
let filteredAnswer = originalAnswer.replace(/\([^)]*\)/g, '').trim()
let filteredAnswer = originalAnswer.replace(/\([^)]*\)/g, '')
// 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
filteredAnswer = filteredAnswer.replace(/\[参考文档(?:[^]*》\s*)+\]/g, '').trim()
filteredAnswer = filteredAnswer.replace(/\[参考文档(?:[^]*》\s*)+\]/g, '')
// 只移除空格和制表符,保留换行符(避免移除末尾的 \n\n)
filteredAnswer = trimSpacesOnly(filteredAnswer)
newItems[lastIndex] = {
...newItems[lastIndex],
......
/**
* 只移除字符串开头和结尾的空格和制表符,保留换行符
* 用于流式处理时保留末尾的 \n\n 换行符
*/
export function trimSpacesOnly(text: string): string {
return text.replace(/^[ \t]+|[ \t]+$/g, '')
}
export function formatMarkdown(text: string): string {
// 首先移除 ♪ 符号之后的所有文本
let formattedText = text.split('♪')[0].trim()
// 使用 trimSpacesOnly 保留换行符,避免移除末尾的 \n\n
let formattedText = text.split('♪')[0]
formattedText = trimSpacesOnly(formattedText)
// 处理换行
formattedText = formattedText.replace(/(?<!\n)\n(?!\n)/g, ' \n')
// 先处理连续的换行符(\n\n 或更多),确保它们被保留为段落分隔
// 然后将单独的 \n 替换为 Markdown 的硬换行(两个空格 + \n)
// 注意:\n\n 在 Markdown 中表示段落分隔,应该被保留
formattedText = formattedText.replace(/\n{3,}/g, '\n\n') // 将3个或更多连续换行符压缩为2个
formattedText = formattedText.replace(/(?<!\n)\n(?!\n)/g, ' \n') // 单独的 \n 转换为硬换行
// 处理代码块
formattedText = formattedText.replace(/```(\w+)?\n([\s\S]*?)\n```/g, (match, language, code) => {
......
......@@ -8,6 +8,7 @@ import styles from '../Chat/Chat.module.less'
import { processApiResponse } from '../Chat/helper'
import { ChatItemUser } from '../Chat/components/ChatItem/ChatItemUser'
import { ChatAnswerBox } from '../Chat/components/ChatItem/ChatAnswerBox'
import { trimSpacesOnly } from '../Chat/components/ChatItem/markdownFormatter'
import { TacticsWelcome } from './components/TacticsWelcome'
import DeleteIcon from '@/assets/svg/delete.svg?react'
import RefreshIcon from '@/assets/svg/refresh.svg?react'
......@@ -282,9 +283,11 @@ export const TacticsChat: React.FC = () => {
// 移除 ♪ 符号之后的所有文本(与历史记录保持一致)
let filteredAnswer = originalAnswer.split('♪')[0]
// 移除所有括号及其内容
filteredAnswer = filteredAnswer.replace(/\([^)]*\)/g, '').trim()
filteredAnswer = filteredAnswer.replace(/\([^)]*\)/g, '')
// 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
filteredAnswer = filteredAnswer.replace(/\[参考文档(?:[^]*》\s*)+\]/g, '').trim()
filteredAnswer = filteredAnswer.replace(/\[参考文档(?:[^]*》\s*)+\]/g, '')
// 只移除空格和制表符,保留换行符(避免移除末尾的 \n\n)
filteredAnswer = trimSpacesOnly(filteredAnswer)
newItems[lastAiIndex] = {
...newItems[lastAiIndex],
......@@ -312,9 +315,11 @@ export const TacticsChat: React.FC = () => {
// 移除 ♪ 符号之后的所有文本(与历史记录保持一致)
let filteredAnswer = newAnswer.split('♪')[0]
// 移除所有括号及其内容
filteredAnswer = filteredAnswer.replace(/\([^)]*\)/g, '').trim()
filteredAnswer = filteredAnswer.replace(/\([^)]*\)/g, '')
// 去除 [参考文档《任意内容》 《任意内容》...] 格式的内容
filteredAnswer = filteredAnswer.replace(/\[参考文档(?:[^]*》\s*)+\]/g, '').trim()
filteredAnswer = filteredAnswer.replace(/\[参考文档(?:[^]*》\s*)+\]/g, '')
// 只移除空格和制表符,保留换行符(避免移除末尾的 \n\n)
filteredAnswer = trimSpacesOnly(filteredAnswer)
newItems.push({
role: 'ai',
question,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment