bugfix: 多条消息的卡片展示

This commit is contained in:
2026-04-01 16:59:22 +08:00
parent 72cd9d28f2
commit 63313d2d81
4 changed files with 36 additions and 89 deletions

View File

@@ -353,10 +353,7 @@
}) })
} }
}) })
// 通知 Preview 有新 sketch 正在加载,传入 sketch 索引
MyEvent.emit('loading-sketch', sketchList.value.length - 1)
MyEvent.emit('OpenSketch') MyEvent.emit('OpenSketch')
// contentBody += `<slot slot-name="sketch"></slot>`
} }
if (eventName === 'reportName' || eventName === 'reportTitle') { if (eventName === 'reportName' || eventName === 'reportTitle') {
aiMessage.reportName = jsonData.reportName || jsonData.reportTitle aiMessage.reportName = jsonData.reportName || jsonData.reportTitle
@@ -470,13 +467,7 @@
} }
// 处理对话列表,将连续的 assistant 消息合并为一条 // 处理对话列表,将连续的 assistant 消息合并为一条
const processDialogue = ( const processDialogue = (dialogue, startIndex, existingImgList, sessionId) => {
dialogue,
startIndex,
existingImgList,
sessionId,
firstReportIndex = -1
) => {
if (!dialogue || dialogue.length === 0) return [] if (!dialogue || dialogue.length === 0) return []
const result = [] const result = []
@@ -485,7 +476,6 @@
while (i < dialogue.length) { while (i < dialogue.length) {
const item = dialogue[i] const item = dialogue[i]
if (item.role === 'user') { if (item.role === 'user') {
// user 角色直接添加
result.push({ result.push({
...item, ...item,
text: item.content, text: item.content,
@@ -495,42 +485,42 @@
}) })
i++ i++
} else if (item.role === 'assistant') { } else if (item.role === 'assistant') {
// assistant 角色,拼接直到下一个 user
let combinedContent = item.content || '' let combinedContent = item.content || ''
let combinedThinkingText = item.reasoning || '' let combinedThinkingText = item.reasoning || ''
let combinedImageUrl = item.image_url || null let combinedImageUrl = item.image_url || null
let reportName = item.reportName || null let reportName = item.reportName || null
let webAddress = item.webAddress || null let webAddress = item.webAddress || null
// 继续往后找连续的 assistant 消息 let combinedReport = item.report || ''
let hasReportSlot = !!item.report
let hasUrlSlot = !!item.webAddress
let j = i + 1 let j = i + 1
while (j < dialogue.length && dialogue[j].role === 'assistant') { while (j < dialogue.length && dialogue[j].role === 'assistant') {
combinedContent += dialogue[j].content || '' const next = dialogue[j]
combinedThinkingText += dialogue[j].reasoning || '' combinedContent += next.content || ''
// 如果有 image_url 则保留 combinedThinkingText += next.reasoning || ''
if (dialogue[j].image_url) { combinedReport += next.report || ''
combinedImageUrl = dialogue[j].image_url if (next.image_url) combinedImageUrl = next.image_url
} if (next.reportName) reportName = next.reportName
if (dialogue[j].reportName) { if (next.report) hasReportSlot = true
reportName = dialogue[j].reportName if (next.webAddress) {
} webAddress = next.webAddress
if (dialogue[j].webAddress) { hasUrlSlot = true
combinedContent += `<slot slot-name="url"></slot>`
webAddress = dialogue[j].webAddress
// console.log('webAddress22222222222222', dialogue[j].webAddress)
// debugger
} }
j++ j++
} }
// 如果 firstReportIndex 在当前合并范围内,则把 slot 追加到末尾 if (hasUrlSlot) {
if (firstReportIndex >= i && firstReportIndex < j) { combinedContent += `<slot slot-name="url"></slot>`
}
if (hasReportSlot) {
combinedContent += `<slot slot-name="card" title="Report" content="Report"></slot>` combinedContent += `<slot slot-name="card" title="Report" content="Report"></slot>`
} }
result.push({ result.push({
...item, ...item,
reportName, reportName,
report: combinedReport,
content: combinedContent, content: combinedContent,
thinkingText: combinedThinkingText, thinkingText: combinedThinkingText,
text: combinedContent, text: combinedContent,
@@ -543,7 +533,6 @@
i = j i = j
} else { } else {
// 其他角色直接添加
result.push({ result.push({
...item, ...item,
text: item.content, text: item.content,
@@ -560,35 +549,11 @@
const processSession = (session, imgList, ancestorsList, idCounterRef) => { const processSession = (session, imgList, ancestorsList, idCounterRef) => {
if (!session) return if (!session) return
// 1. 找到第一个 report 项的索引,供 processDialogue 使用
let firstReportIndex = -1
if (session.dialogue) {
for (let i = 0; i < session.dialogue.length; i++) {
if (session.dialogue[i].report) {
firstReportIndex = i
break
}
}
}
// 2. 收集 report 内容并保存到 sessionStorage
let reportStr = ''
session.dialogue?.forEach((item) => {
if (item.report) {
reportStr += item.report
}
})
if (reportStr && session.id) {
sessionStorage.setItem(`reportsContent_${session.id}`, reportStr)
}
// 3. 收集 sketchIDAndUrl 到 imgList
if (session.sketchIDAndUrl) { if (session.sketchIDAndUrl) {
imgList.push(session.sketchIDAndUrl) imgList.push(session.sketchIDAndUrl)
} }
// 4. 处理 dialogue const list = processDialogue(session.dialogue, 0, imgList, session.id)
const list = processDialogue(session.dialogue, 0, imgList, session.id, firstReportIndex)
list.forEach((el) => { list.forEach((el) => {
el.id = idCounterRef.value++ el.id = idCounterRef.value++
}) })
@@ -636,6 +601,7 @@
item.text += `<slot slot-name="sketch"></slot>` item.text += `<slot slot-name="sketch"></slot>`
} }
}) })
console.log('ancestorslist', ancestorsList)
messageList.value = [...ancestorsList] messageList.value = [...ancestorsList]
params.versionID = current?.id params.versionID = current?.id
sketchList.value = imgList sketchList.value = imgList

View File

@@ -2,7 +2,7 @@
<div class="agent-list flex flex-col flex-1" ref="listContainer"> <div class="agent-list flex flex-col flex-1" ref="listContainer">
<Item <Item
v-for="(message, index) in messageList" v-for="(message, index) in messageList"
:key="message.id" :key="message.id + index"
:content="message" :content="message"
:is-last="index === messageList.length - 1" :is-last="index === messageList.length - 1"
@regenerate="$emit('regenerate', message)" @regenerate="$emit('regenerate', message)"

View File

@@ -44,10 +44,7 @@
<img src="@/assets/images/arrow-top-right.png" /> <img src="@/assets/images/arrow-top-right.png" />
</div> </div>
<!-- 已加载完成的 sketch 显示实际图片 --> <!-- 已加载完成的 sketch 显示实际图片 -->
<img <img v-img-loading="getImageSrc(item, index)" @load="handleImageLoad(index)" />
v-img-loading="getImageSrc(item, index)"
@load="handleImageLoad(index)"
/>
<!-- 正在加载的 sketch 显示 loading gif overlay --> <!-- 正在加载的 sketch 显示 loading gif overlay -->
<!-- <div v-if="pendingSketchIndexes.includes(index)" class="loading-wrapper"> <!-- <div v-if="pendingSketchIndexes.includes(index)" class="loading-wrapper">
<img src="@/assets/images/sketch-loading.gif" alt="loading" /> <img src="@/assets/images/sketch-loading.gif" alt="loading" />
@@ -118,8 +115,6 @@
// 存储每个图片的加载状态 // 存储每个图片的加载状态
const loadedStatus = ref<boolean[]>([]) const loadedStatus = ref<boolean[]>([])
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
type: 'sketch' | 'report' | 'url' type: 'sketch' | 'report' | 'url'
@@ -187,8 +182,9 @@
sessionId.value = id sessionId.value = id
} }
const setReportTitle = (title: string) => { const setReport = (title: string, content: string) => {
reportTitle.value = title reportTitle.value = title
markdownContent.value = content
} }
const setUrls = async (list: string[]) => { const setUrls = async (list: string[]) => {
@@ -196,14 +192,14 @@
const res = await fetchUrlTitle(list) const res = await fetchUrlTitle(list)
urlList.value = res urlList.value = res
} }
watch( // watch(
() => sessionId.value, // () => sessionId.value,
(newVal) => { // (newVal) => {
if (newVal) { // if (newVal) {
markdownContent.value = sessionStorage.getItem(`reportsContent_${newVal}`) // markdownContent.value = sessionStorage.getItem(`reportsContent_${newVal}`)
} // }
} // }
) // )
// 图片加载完成时触发 // 图片加载完成时触发
const handleImageLoad = (index: number) => { const handleImageLoad = (index: number) => {
@@ -264,15 +260,6 @@
URL.revokeObjectURL(url) URL.revokeObjectURL(url)
} }
const showLoading = ref(false)
const handleLoadingSketch = (sketchIndex?: number) => {
showLoading.value = true
// 记录正在加载的 sketch 索引
// if (sketchIndex !== undefined) {
// pendingSketchIndexes.value.push(sketchIndex)
// }
}
const handleClickUrl = (item: { url: string; title: string }) => { const handleClickUrl = (item: { url: string; title: string }) => {
window.open(item.url, '_blank') window.open(item.url, '_blank')
} }
@@ -316,17 +303,11 @@
} }
} }
} }
onMounted(() => {
MyEvent.add('loading-sketch', handleLoadingSketch)
})
onUnmounted(() => {
MyEvent.remove('loading-sketch', handleLoadingSketch)
})
defineExpose({ defineExpose({
setSessionId, setSessionId,
setUrls, setUrls,
setReportTitle setReport
}) })
</script> </script>

View File

@@ -116,7 +116,7 @@
const handleOpenReport = (data) => { const handleOpenReport = (data) => {
previewRef.value.setSessionId(data.sessionId) previewRef.value.setSessionId(data.sessionId)
previewRef.value.setReportTitle(data.reportName) previewRef.value.setReport(data.reportName, data.report)
previewType.value = 'report' previewType.value = 'report'
} }