Browse Source

【功能新增】AI:聊天记录返回时,增加 segments

YunaiV 5 months ago
parent
commit
fc9995d8c8
1 changed files with 104 additions and 0 deletions
  1. 104 0
      src/views/ai/chat/index/components/message/MessageKnowledge.vue

+ 104 - 0
src/views/ai/chat/index/components/message/MessageKnowledge.vue

@@ -0,0 +1,104 @@
+<!-- 知识引用组件 -->
+<template>
+  <!-- 知识引用列表 -->
+  <div v-if="segments && segments.length > 0" class="mt-10px p-10px rounded-8px bg-[#f5f5f5]">
+    <div class="text-14px text-[#666] mb-8px flex items-center">
+      <Icon icon="ep:document" class="mr-5px" /> 知识引用
+    </div>
+    <div class="flex flex-wrap gap-8px">
+      <div
+        v-for="(doc, index) in documentList"
+        :key="index"
+        class="p-8px px-12px bg-white rounded-6px cursor-pointer transition-all hover:bg-[#e6f4ff]"
+        @click="handleClick(doc)"
+      >
+        <div class="text-14px text-[#333] mb-4px">
+          {{ doc.title }}
+          <span class="text-12px text-[#999] ml-4px">({{ doc.segments.length }} 条)</span>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <!-- 知识引用详情弹窗 -->
+  <el-popover
+    v-model:visible="dialogVisible"
+    :width="600"
+    trigger="click"
+    placement="top-start"
+    :offset="55"
+    popper-class="knowledge-popover"
+  >
+    <template #reference>
+      <div ref="documentRef"></div>
+    </template>
+    <template #default>
+      <div class="text-16px font-bold mb-12px">{{ document?.title }}</div>
+      <div class="max-h-[60vh] overflow-y-auto">
+        <div
+          v-for="(segment, index) in document?.segments"
+          :key="index"
+          class="p-12px border-b-solid border-b-[#eee] last:border-b-0"
+        >
+          <div
+            class="block mb-8px px-8px py-2px bg-[#f5f5f5] rounded-4px text-12px text-[#666] w-fit"
+          >
+            分段 {{ segment.id }}
+          </div>
+          <div class="text-14px leading-[1.6] text-[#333] mt-[10px]">
+            {{ segment.content }}
+          </div>
+        </div>
+      </div>
+    </template>
+  </el-popover>
+</template>
+
+<script setup lang="ts">
+const props = defineProps<{
+  segments: {
+    id: number
+    documentId: number
+    documentName: string
+    content: string
+  }[]
+}>()
+
+const document = ref<{
+  id: number
+  title: string
+  segments: {
+    id: number
+    content: string
+  }[]
+} | null>(null) // 知识库文档列表
+const dialogVisible = ref(false) // 知识引用详情弹窗
+const documentRef = ref<HTMLElement>() // 知识引用详情弹窗 Ref
+
+/** 按照 document 聚合 segments */
+const documentList = computed(() => {
+  if (!props.segments) return []
+
+  const docMap = new Map()
+  props.segments.forEach((segment) => {
+    if (!docMap.has(segment.documentId)) {
+      docMap.set(segment.documentId, {
+        id: segment.documentId,
+        title: segment.documentName,
+        segments: []
+      })
+    }
+    docMap.get(segment.documentId).segments.push({
+      id: segment.id,
+      content: segment.content
+    })
+  })
+  return Array.from(docMap.values())
+})
+
+/** 点击 document 处理 */
+const handleClick = (doc: any) => {
+  document.value = doc
+  dialogVisible.value = true
+}
+</script>