MessageKnowledge.vue
2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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>