feat: 报告初步显示
This commit is contained in:
@@ -33,7 +33,10 @@
|
||||
const agentStore = useAgentStore()
|
||||
const projectStore = useProjectStore()
|
||||
|
||||
const emits = defineEmits(['update:sketchList'])
|
||||
const reportsContent = ref('')
|
||||
const isGeneratingReport = ref(false)
|
||||
|
||||
const emits = defineEmits(['update:sketchList', 'setTitle'])
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
title: string
|
||||
@@ -206,6 +209,7 @@
|
||||
// 流式响应处理
|
||||
let contentBody = ''
|
||||
let buffer = ''
|
||||
const webAddressList = []
|
||||
const reader = response.body?.getReader()
|
||||
if (!reader) throw new Error('无法获取流读取器')
|
||||
|
||||
@@ -230,18 +234,43 @@
|
||||
let events = buffer.split(/\n\n/)
|
||||
buffer = events.pop() // 保留不完整块
|
||||
|
||||
let previousEventName = '' // 记录上一个事件名称
|
||||
let hasReportStarted = false // 标记 report 是否已经开始
|
||||
|
||||
for (let event of events) {
|
||||
if (!event.trim()) continue
|
||||
// debugger
|
||||
// 过滤掉 id: 等字段,只取 data:
|
||||
|
||||
let isNodeIdEvent = false
|
||||
if (event.includes('nodeId')) {
|
||||
isNodeIdEvent = true
|
||||
// continue
|
||||
// 解析事件名称(从 event:xxx 行)
|
||||
const eventName =
|
||||
event
|
||||
.split(/\n/)
|
||||
.find((line) => line.startsWith('event:'))
|
||||
?.replace(/^event:\s*/, '')
|
||||
?.trim() || ''
|
||||
|
||||
if (!hasReportStarted && eventName === 'report') {
|
||||
console.log('开始生成报告--------')
|
||||
|
||||
isGeneratingReport.value = true
|
||||
contentBody += `<slot slot-name="card" title="123">123</slot>`
|
||||
hasReportStarted = true
|
||||
}
|
||||
console.log('event', event)
|
||||
if (event.includes('error')) {
|
||||
|
||||
if (
|
||||
previousEventName === 'report' &&
|
||||
eventName !== 'report' &&
|
||||
reportsContent.value
|
||||
) {
|
||||
isGeneratingReport.value = false
|
||||
localStorage.setItem('reportsContent', reportsContent.value)
|
||||
}
|
||||
|
||||
previousEventName = eventName
|
||||
|
||||
// console.log('eventName:', eventName, 'event:', event)
|
||||
|
||||
// 根据事件名称精确判断,而不是用 includes
|
||||
if (eventName === 'error') {
|
||||
aiMessage.text = '出现错误,请重试'
|
||||
aiMessage.streaming = false
|
||||
aiMessage.loading = false
|
||||
@@ -249,27 +278,29 @@
|
||||
flag = false
|
||||
break
|
||||
}
|
||||
// TODO: 暂时不处理webAddress
|
||||
if (event.includes('todo')) {
|
||||
if (eventName === 'todo') {
|
||||
break
|
||||
}
|
||||
let hasSketch = false
|
||||
if (event.includes('sketchIDAndUrl')) {
|
||||
hasSketch = true
|
||||
}
|
||||
|
||||
let isNodeIdEvent = eventName === 'nodeId'
|
||||
|
||||
let hasSketch = eventName === 'sketch'
|
||||
|
||||
const dataLines = event
|
||||
.split(/\n/)
|
||||
.filter((line) => line.startsWith('data:'))
|
||||
.map((line) => line.replace(/^data:\s*/, '').trim())
|
||||
.map((line) => line.replace(/^data:\s*/, ''))
|
||||
.filter((content) => content.startsWith('{') || content.startsWith('['))
|
||||
console.log('dataLInes', dataLines)
|
||||
// console.log('dataLInes', dataLines)
|
||||
if (isNodeIdEvent) {
|
||||
params.versionID = dataLines[0]
|
||||
projectStore.setProject({ nodeId: dataLines[0] })
|
||||
}
|
||||
if (eventName === 'webAddress') {
|
||||
console.log('webAddress-----', eventName, dataLines)
|
||||
}
|
||||
|
||||
if (event.includes('tool')) {
|
||||
if (eventName === 'tool') {
|
||||
MyEvent.emit('loading-sketch')
|
||||
}
|
||||
|
||||
@@ -278,21 +309,38 @@
|
||||
|
||||
try {
|
||||
const jsonData = JSON.parse(jsonText)
|
||||
console.log('jsonData', jsonData)
|
||||
// console.log('jsonData', jsonData)
|
||||
if (jsonData.webAddress) {
|
||||
console.log('webAddress-----', jsonData)
|
||||
}
|
||||
if (jsonData.title) {
|
||||
emits('setTitle', jsonData.title)
|
||||
}
|
||||
|
||||
if (hasSketch) {
|
||||
sketchList.value.push({
|
||||
[Object.keys(jsonData)[0]]: jsonData[Object.keys(jsonData)[0]]
|
||||
})
|
||||
}
|
||||
if (
|
||||
jsonData.content &&
|
||||
jsonData.content.length > 0 &&
|
||||
jsonData.type !== 'end'
|
||||
) {
|
||||
contentBody += jsonData.content
|
||||
aiMessage.text = contentBody
|
||||
aiMessage.loading = false
|
||||
if (eventName === 'report') {
|
||||
reportsContent.value += jsonData.content
|
||||
} else {
|
||||
if (jsonData.reasoning) {
|
||||
aiMessage.thinking = true
|
||||
aiMessage.loading = false
|
||||
aiMessage.thinkingText += jsonData.reasoning
|
||||
} else {
|
||||
aiMessage.thinking = false
|
||||
if (
|
||||
jsonData.content &&
|
||||
jsonData.content.length > 0 &&
|
||||
jsonData.type !== 'end'
|
||||
) {
|
||||
contentBody += jsonData.content
|
||||
aiMessage.text = contentBody
|
||||
aiMessage.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (jsonData.type === 'end') {
|
||||
aiMessage.streaming = false
|
||||
@@ -319,6 +367,9 @@
|
||||
console.warn('⚠️ JSON 格式错误,跳过:', jsonText)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新上一个事件名称
|
||||
previousEventName = eventName
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -378,7 +429,7 @@
|
||||
}
|
||||
|
||||
// 处理对话列表,将连续的 assistant 消息合并为一条
|
||||
const processDialogue = (dialogue, startIndex, existingImgList) => {
|
||||
const processDialogue = (dialogue, startIndex, existingImgList, sessionId) => {
|
||||
if (!dialogue || dialogue.length === 0) return []
|
||||
|
||||
const result = []
|
||||
@@ -393,26 +444,30 @@
|
||||
...item,
|
||||
text: item.content,
|
||||
isUser: true,
|
||||
id: result.length + 1
|
||||
id: result.length + 1,
|
||||
sessionId: sessionId
|
||||
})
|
||||
i++
|
||||
} else if (item.role === 'assistant') {
|
||||
// assistant 角色,拼接直到下一个 user
|
||||
let combinedContent = item.content || ''
|
||||
|
||||
let combinedThinkingText = item.reasoning || ''
|
||||
// 继续往后找连续的 assistant 消息
|
||||
let j = i + 1
|
||||
while (j < dialogue.length && dialogue[j].role === 'assistant') {
|
||||
combinedContent += dialogue[j].content || ''
|
||||
combinedThinkingText += dialogue[j].reasoning || ''
|
||||
j++
|
||||
}
|
||||
|
||||
result.push({
|
||||
...item,
|
||||
content: combinedContent,
|
||||
thinkingText: combinedThinkingText,
|
||||
text: combinedContent,
|
||||
isUser: false,
|
||||
id: result.length + 1
|
||||
id: result.length + 1,
|
||||
sessionId: sessionId
|
||||
})
|
||||
|
||||
i = j
|
||||
@@ -422,7 +477,8 @@
|
||||
...item,
|
||||
text: item.content,
|
||||
isUser: item.role === 'user',
|
||||
id: result.length + 1
|
||||
id: result.length + 1,
|
||||
sessionId: sessionId
|
||||
})
|
||||
i++
|
||||
}
|
||||
@@ -430,6 +486,44 @@
|
||||
|
||||
return result
|
||||
}
|
||||
const processSession = (session, imgList, ancestorsList, idCounterRef) => {
|
||||
if (!session) return
|
||||
|
||||
// 1. 在 dialogue 第一个 report 有值的项的 content 中插入报告卡片
|
||||
if (session.dialogue) {
|
||||
for (let i = 0; i < session.dialogue.length; i++) {
|
||||
if (session.dialogue[i].report) {
|
||||
session.dialogue[i].content =
|
||||
`<slot slot-name="card" title="123">123</slot>` +
|
||||
(session.dialogue[i].content || '')
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 收集 report 内容并保存到 localStorage
|
||||
let reportStr = ''
|
||||
session.dialogue?.forEach((item) => {
|
||||
if (item.report) {
|
||||
reportStr += item.report
|
||||
}
|
||||
})
|
||||
if (reportStr && session.id) {
|
||||
localStorage.setItem(`reportsContent_${session.id}`, reportStr)
|
||||
}
|
||||
|
||||
// 3. 收集 sketchIDAndUrl 到 imgList
|
||||
if (session.sketchIDAndUrl) {
|
||||
imgList.push(...session.sketchIDAndUrl)
|
||||
}
|
||||
|
||||
// 4. 处理 dialogue
|
||||
const list = processDialogue(session.dialogue, 0, imgList, session.id)
|
||||
list.forEach((el) => {
|
||||
el.id = idCounterRef.value++
|
||||
})
|
||||
ancestorsList.push(...list)
|
||||
}
|
||||
|
||||
const setChatInfo = (info) => {
|
||||
const initialData = agentStore.getInitialProjectData
|
||||
@@ -454,37 +548,25 @@
|
||||
messageList.value = []
|
||||
return
|
||||
}
|
||||
|
||||
const { ancestors, current } = data
|
||||
|
||||
let imgList = []
|
||||
const ancestorsList = []
|
||||
let ancestorsIdCounter = 1
|
||||
if (ancestors) {
|
||||
ancestors.forEach((item) => {
|
||||
if (item.sketchIDAndUrl) {
|
||||
imgList = imgList.concat(item.sketchIDAndUrl)
|
||||
}
|
||||
const list = processDialogue(item.dialogue, 0, imgList)
|
||||
// 重新设置 id
|
||||
list.forEach((el) => {
|
||||
el.id = ancestorsIdCounter++
|
||||
})
|
||||
ancestorsList.push(...list)
|
||||
})
|
||||
}
|
||||
const currentList = processDialogue(current?.dialogue, 0, imgList)
|
||||
if (current.sketchIDAndUrl) {
|
||||
imgList = imgList.concat(current.sketchIDAndUrl)
|
||||
}
|
||||
// 处理单个会话(ancestor 或 current)
|
||||
|
||||
currentList.forEach((el, index) => {
|
||||
el.id = index + 1 + ancestorsList.length
|
||||
const imgList = []
|
||||
const ancestorsList = []
|
||||
const idCounterRef = { value: 1 }
|
||||
|
||||
// 处理所有 ancestors
|
||||
ancestors?.forEach((item) => {
|
||||
processSession(item, imgList, ancestorsList, idCounterRef)
|
||||
})
|
||||
|
||||
// 处理 current
|
||||
processSession(current, imgList, ancestorsList, idCounterRef)
|
||||
|
||||
// 延迟设置新数据,确保 UI 有时间响应清空操作
|
||||
nextTick(() => {
|
||||
messageList.value = [...ancestorsList, ...currentList]
|
||||
messageList.value = [...ancestorsList]
|
||||
params.versionID = current?.id
|
||||
sketchList.value = imgList
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user