diff --git a/src/pages/ReportPage.vue b/src/pages/ReportPage.vue index 6b8971d..8a865e2 100644 --- a/src/pages/ReportPage.vue +++ b/src/pages/ReportPage.vue @@ -220,11 +220,7 @@ function dimensionConclusion(item: { 蝶雅产品部 · 风险预警系统 · 自动生成 · {{ generatedAt }}

- 产品/评估对象:{{ report.subjectId }} - >供应商:{{ report.supplierFreq?.supplierName || "未指定" }}报告编号:RP-{{ report.subjectId.slice(0, 8) }}-{{ report.score.toFixed(0) }} import axios from "axios"; -import { computed, nextTick, onMounted, ref, watch } from "vue"; +import { computed, nextTick, onActivated, onMounted, ref, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; import AssistantComposer from "@/components/assistant/AssistantComposer.vue"; @@ -45,6 +45,7 @@ const tool = ref< const toolInput = ref(""); const toolError = ref(""); const toolFile = ref(null); +const expandedReplies = ref(new Set()); const assessmentFields = ref({ category: "", specification: "", @@ -110,6 +111,12 @@ onMounted(async () => { await openFromRoute(); }); +onActivated(async () => { + // MainLayout keeps this page alive. Returning from report/dashboard therefore + // does not remount it, so explicitly reveal the newest message on re-entry. + if (conversation.value?.messages.length) await scrollToBottom("auto"); +}); + watch( () => route.query.conversation, async () => { @@ -124,6 +131,40 @@ async function usePrompt(value: string) { composer.value?.focus(); } +function toggleReply(messageId: number) { + const next = new Set(expandedReplies.value); + if (next.has(messageId)) next.delete(messageId); + else next.add(messageId); + expandedReplies.value = next; +} + +function canCollapseReply(content: string) { + return content.trim().length > 90; +} + +function isMessageThinking(messageId: number, index: number) { + const messages = conversation.value?.messages ?? []; + return ( + generating.value && + index === messages.length - 1 && + messages[index]?.id === messageId && + messages[index]?.role === "assistant" + ); +} + +function thinkingDuration(index: number) { + const messages = conversation.value?.messages ?? []; + const message = messages[index]; + const previous = messages[index - 1]; + if (!message || !previous || previous.role !== "user") return null; + const elapsed = Math.round( + (new Date(message.createdAt).getTime() - + new Date(previous.createdAt).getTime()) / + 1000, + ); + return elapsed > 0 ? elapsed : null; +} + function openTool( value: | "assessment" @@ -275,7 +316,11 @@ async function openFromRoute() { const rawId = route.query.conversation; if (typeof rawId !== "string") return; const id = Number(rawId); - if (Number.isSafeInteger(id) && id > 0 && conversation.value?.id !== id) { + if (Number.isSafeInteger(id) && id > 0 && conversation.value?.id === id) { + await scrollToBottom("auto"); + return; + } + if (Number.isSafeInteger(id) && id > 0) { try { await conversationStore.open(id); await scrollToBottom("auto"); @@ -436,7 +481,7 @@ async function scrollToBottom(behavior: "smooth" | "auto" = "smooth") { />