From d04e8888cb73740dd8f6f0121719da3807d50d8f Mon Sep 17 00:00:00 2001 From: kx_guo Date: Fri, 18 Sep 2026 11:37:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=A1=88=E4=BE=8B=E5=8D=A1?= =?UTF-8?q?=E7=89=87=E5=92=8C=E6=80=9D=E8=80=83=E8=BF=87=E7=A8=8B=E5=B1=95?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/conversations.ts | 6 +- .../assistant/AssistantComposer.vue | 38 ++- .../assistant/AssistantResponseCard.vue | 240 +++++++++++++++++- src/pages/RiskAssistantPage.vue | 169 +++++++++++- src/types/conversation.ts | 2 +- 5 files changed, 428 insertions(+), 27 deletions(-) diff --git a/src/api/conversations.ts b/src/api/conversations.ts index 11d3139..503e6f7 100644 --- a/src/api/conversations.ts +++ b/src/api/conversations.ts @@ -1,6 +1,6 @@ import { http } from "@/api/http"; -import type { ApiResponse } from "@/types/api"; import type { Conversation, ConversationSummary } from "@/types/conversation"; +import type { ApiResponse } from "@/types/api"; export interface ConversationStreamEvent { type: "start" | "semantic" | "delta" | "done" | "error"; @@ -22,6 +22,10 @@ export function createConversation(title?: string) { }); } +export function directConversationQuery(kind: "supplier" | "material" | "cases" | "solution", query: string) { + return http.post>>("/v1/conversations/direct-query", { kind, query }); +} + export function fetchConversation(id: number, offset = 0) { return http.get>(`/v1/conversations/${id}`, { params: { limit: 20, offset }, diff --git a/src/components/assistant/AssistantComposer.vue b/src/components/assistant/AssistantComposer.vue index 5cb4c99..b84b7ac 100644 --- a/src/components/assistant/AssistantComposer.vue +++ b/src/components/assistant/AssistantComposer.vue @@ -47,6 +47,7 @@ const functions: Array<{ icon: typeof Search; tone: string; prompt?: string; + isNew?: boolean; tool: "assessment" | "supplier" | "material" | "cases" | "solution" | "review"; }> = [ @@ -89,6 +90,7 @@ const functions: Array<{ tone: "purple", prompt: "帮我生成一个新品风险预防方案", tool: "solution", + isNew: true, }, { title: "审核队列", @@ -96,6 +98,7 @@ const functions: Array<{ icon: ClipboardCheck, tone: "red", tool: "review", + isNew: true, }, ]; @@ -155,14 +158,11 @@ const functions: Array<{ :key="item.title" class="function-card" type="button" - @click=" - item.tool === 'assessment' || !item.prompt - ? emit('tool', item.tool) - : emit('select', item.prompt) - " + @click="emit('tool', item.tool)" > + 新 {{ item.title }}{{ item.description }} span:last-child { @@ -292,12 +296,26 @@ const functions: Array<{ .function-card strong { color: var(--color-text); - font-size: 10px; + font-size: 11px; + font-weight: 600; } .function-card small { color: var(--color-text-faint); + font-size: 9px; + margin-top: 1px; +} + +.function-new { + position: absolute; + top: 2px; + right: 2px; + border-radius: 3px; + padding: 0 4px; + background: var(--color-accent-subtle); + color: var(--color-accent); font-size: 8px; + font-weight: 700; } .function-dot { diff --git a/src/components/assistant/AssistantResponseCard.vue b/src/components/assistant/AssistantResponseCard.vue index 64791d7..227ce31 100644 --- a/src/components/assistant/AssistantResponseCard.vue +++ b/src/components/assistant/AssistantResponseCard.vue @@ -7,8 +7,10 @@ import { Building2, CheckCircle2, ClipboardCheck, + ChevronDown, PackageSearch, Ruler, + Search, Sparkles, } from "@lucide/vue"; import { computed, ref } from "vue"; @@ -24,6 +26,7 @@ const props = defineProps<{ const router = useRouter(); const emit = defineEmits<{ generateReport: [card: ReportCard]; + openAssessment: []; }>(); interface CardData extends AssistantResponseCard { name?: string; @@ -42,7 +45,6 @@ interface CardData extends AssistantResponseCard { suggestions?: string[]; note?: string; detectedValues?: Array<{ name: string; value: string }>; - matchedCount?: number; standards?: Array<{ category: string; riskPoint: string; @@ -50,7 +52,17 @@ interface CardData extends AssistantResponseCard { source?: string | null; status: string; }>; + cases?: Array<{ + caseId?: number | null; + date?: string | null; + product?: string | null; + problem?: string | null; + solution?: string | null; + similarity?: number | null; + }>; + matchedCount?: number; confidence?: string; + thinkingSummary?: string[]; analysisBase?: string; risks?: Array<{ level: string; title: string; detail: string }>; similarCases?: Array<{ @@ -79,6 +91,7 @@ interface CardData extends AssistantResponseCard { const data = computed(() => props.card as CardData); type SolutionCase = NonNullable[number]; const selectedCase = ref(null); +const thinkingExpanded = ref(false); const standardCategories = computed(() => [...new Set((data.value.standards ?? []).map((item) => item.category))].join( " / ", @@ -135,6 +148,7 @@ function generateReport() { +
@@ -151,11 +165,17 @@ function generateReport() { AI 推理生成 · 置信度:{{ data.confidence }} + 匹配 {{ data.matchedCount ?? data.cases?.length ?? 0 }} 条相似历史案例 标准库规则匹配 · 待品控确认
置信度:{{ data.confidence || "中" }} + 语义检索 + + + +
蝶
@@ -686,11 +747,49 @@ async function scrollToBottom(behavior: "smooth" | "auto" = "smooth") { />

{{ toolError }}

+
+ + + + +
-
@@ -1070,6 +1169,52 @@ async function scrollToBottom(behavior: "smooth" | "auto" = "smooth") { color: white; } +.direct-result-card { + margin-top: 14px; + border: 1px solid var(--color-border); + border-radius: 9px; + padding: 16px; + background: var(--color-bg-warm); + color: var(--color-text-secondary); + font-size: 13px; + line-height: 1.75; +} + +.direct-result-card p { + margin: 3px 0; +} + +.direct-result-card strong { + display: block; + margin-bottom: 8px; + color: var(--color-text); + font-size: 14px; +} + +.direct-tier { + display: inline-block !important; + border-radius: 999px; + padding: 3px 10px; + background: var(--color-warning-soft); + color: #92400e !important; + font-size: 11px !important; +} + +.direct-lines { + margin-top: 8px; +} + +.direct-result-card ul, +.direct-result-card ol { + margin: 8px 0 0; + padding-left: 20px; +} + +.direct-case-list li, +.direct-suggestion-list li { + margin: 3px 0; +} + @media (max-width: 760px) { .conversation-column { padding-inline: 12px; diff --git a/src/types/conversation.ts b/src/types/conversation.ts index e6cd8b8..54c3151 100644 --- a/src/types/conversation.ts +++ b/src/types/conversation.ts @@ -1,7 +1,7 @@ import type { RiskAssessmentResult, RiskLevel } from "@/types/risk"; export interface AssistantResponseCard { - type: "supplier" | "material" | "standard" | "compliance" | "solution"; + type: "supplier" | "material" | "standard" | "compliance" | "solution" | "cases"; title: string; [key: string]: unknown; }