From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/views/ai/knowledge/knowledge/retrieval/index.vue |  163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 163 insertions(+), 0 deletions(-)

diff --git a/src/views/ai/knowledge/knowledge/retrieval/index.vue b/src/views/ai/knowledge/knowledge/retrieval/index.vue
new file mode 100644
index 0000000..aca521a
--- /dev/null
+++ b/src/views/ai/knowledge/knowledge/retrieval/index.vue
@@ -0,0 +1,163 @@
+<template>
+  <div class="flex gap-20px w-full">
+    <!-- 宸︿晶杈撳叆鍖哄煙 -->
+    <ContentWrap class="flex-1 min-w-300px">
+      <div class="mb-15px">
+        <h3 class="m-0 mb-5px">鍙洖娴嬭瘯</h3>
+        <div class="text-gray-500 text-14px">鏍规嵁缁欏畾鐨勬煡璇㈡枃鏈祴璇曞彫鍥炴晥鏋溿��</div>
+      </div>
+      <div>
+        <div class="relative mb-10px">
+          <el-input
+            v-model="queryParams.content"
+            type="textarea"
+            :rows="8"
+            placeholder="璇疯緭鍏ユ枃鏈�"
+          />
+          <div class="absolute bottom-10px right-10px text-gray-400 text-12px">
+            {{ queryParams.content?.length }} / 200
+          </div>
+        </div>
+        <div class="flex items-center mb-10px">
+          <span class="w-60px text-gray-500">topK:</span>
+          <el-input-number v-model="queryParams.topK" :min="1" :max="20" />
+        </div>
+        <div class="flex items-center mb-15px">
+          <span class="w-60px text-gray-500">鐩镐技搴�:</span>
+          <el-input-number
+            v-model="queryParams.similarityThreshold"
+            :min="0"
+            :max="1"
+            :precision="2"
+            :step="0.01"
+          />
+        </div>
+        <div class="flex justify-end">
+          <el-button type="primary" @click="getRetrievalResult" :loading="loading">娴嬭瘯</el-button>
+        </div>
+      </div>
+    </ContentWrap>
+
+    <!-- 鍙充晶鍙洖缁撴灉鍖哄煙 -->
+    <ContentWrap class="flex-1 min-w-300px">
+      <el-empty v-if="loading" description="姝e湪妫�绱腑..." />
+      <div v-else-if="segments.length > 0" class="font-bold mb-15px">
+        {{ segments.length }} 涓彫鍥炴钀�
+      </div>
+      <el-empty v-else description="鏆傛棤鍙洖缁撴灉" />
+      <div>
+        <div
+          v-for="(segment, index) in segments"
+          :key="index"
+          class="mb-20px border border-solid border-gray-200 rounded p-15px"
+        >
+          <div class="flex justify-between text-12px text-gray-500 mb-5px">
+            <span>
+              鍒嗘({{ segment.id }}) 路 {{ segment.contentLength }} 瀛楃鏁� 路
+              {{ segment.tokens }} Token
+            </span>
+            <span class="px-8px py-4px bg-blue-50 text-blue-500 rounded-full text-12px font-bold">
+              score: {{ segment.score }}
+            </span>
+          </div>
+          <div
+            class="bg-gray-50 p-10px rounded mb-10px whitespace-pre-wrap overflow-hidden transition-all duration-100 text-13px"
+            :class="{
+              'line-clamp-2 max-h-50px': !segment.expanded,
+              'max-h-500px': segment.expanded
+            }"
+          >
+            {{ segment.content }}
+          </div>
+          <div class="flex justify-between items-center">
+            <div class="flex items-center text-gray-500 text-13px">
+              <Icon icon="ep:document" class="mr-5px" />
+              <span>{{ segment.documentName || '鏈煡鏂囨。' }}</span>
+            </div>
+            <el-button size="small" @click="toggleExpand(segment)">
+              {{ segment.expanded ? '鏀惰捣' : '灞曞紑' }}
+              <Icon :icon="segment.expanded ? 'ep:arrow-up' : 'ep:arrow-down'" />
+            </el-button>
+          </div>
+        </div>
+      </div>
+    </ContentWrap>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { useMessage } from '@/hooks/web/useMessage'
+import { KnowledgeSegmentApi } from '@/api/ai/knowledge/segment'
+import { KnowledgeApi } from '@/api/ai/knowledge/knowledge'
+/** 鏂囨。鍙洖娴嬭瘯 */
+defineOptions({ name: 'KnowledgeDocumentRetrieval' })
+
+const message = useMessage() // 娑堟伅寮圭獥
+const route = useRoute() // 璺敱
+const router = useRouter() // 璺敱
+
+const loading = ref(false) // 鍔犺浇鐘舵��
+const segments = ref<any[]>([]) // 鍙洖缁撴灉
+const queryParams = reactive({
+  id: undefined,
+  content: '',
+  topK: 10,
+  similarityThreshold: 0.5
+})
+
+/** 璋冪敤鏂囨。鍙洖娴嬭瘯鎺ュ彛 */
+const getRetrievalResult = async () => {
+  if (!queryParams.content) {
+    message.warning('璇疯緭鍏ユ煡璇㈡枃鏈�')
+    return
+  }
+
+  loading.value = true
+  segments.value = []
+
+  try {
+    const data = await KnowledgeSegmentApi.searchKnowledgeSegment({
+      knowledgeId: queryParams.id,
+      content: queryParams.content,
+      topK: queryParams.topK,
+      similarityThreshold: queryParams.similarityThreshold
+    })
+    segments.value = data || []
+  } catch (error) {
+    console.error(error)
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 灞曞紑/鏀惰捣娈佃惤鍐呭 */
+const toggleExpand = (segment: any) => {
+  segment.expanded = !segment.expanded
+}
+
+/** 鑾峰彇鐭ヨ瘑搴撲俊鎭� */
+const getKnowledgeInfo = async (id: number) => {
+  try {
+    const knowledge = await KnowledgeApi.getKnowledge(id)
+    if (knowledge) {
+      queryParams.topK = knowledge.topK || queryParams.topK
+      queryParams.similarityThreshold =
+        knowledge.similarityThreshold || queryParams.similarityThreshold
+    }
+  } catch (error) {}
+}
+
+/** 鍒濆鍖� **/
+onMounted(() => {
+  // 濡傛灉鐭ヨ瘑搴� ID 涓嶅瓨鍦紝鏄剧ず閿欒鎻愮ず骞跺叧闂〉闈�
+  if (!route.query.id) {
+    message.error('鐭ヨ瘑搴� ID 涓嶅瓨鍦紝鏃犳硶杩涜鍙洖娴嬭瘯')
+    router.back()
+    return
+  }
+  queryParams.id = route.query.id as any
+
+  // 鑾峰彇鐭ヨ瘑搴撲俊鎭苟璁剧疆榛樿鍊�
+  getKnowledgeInfo(queryParams.id as any)
+})
+</script>

--
Gitblit v1.8.0