2026-02-04 15:19:29 +08:00
|
|
|
|
<template>
|
2026-02-04 17:19:29 +08:00
|
|
|
|
<el-drawer
|
2026-02-04 15:19:29 +08:00
|
|
|
|
v-model="visible"
|
|
|
|
|
|
:title="documentInfo.name || '文档详情'"
|
2026-02-04 17:19:29 +08:00
|
|
|
|
size="80%"
|
|
|
|
|
|
direction="rtl"
|
2026-02-05 11:12:08 +08:00
|
|
|
|
:close-on-click-modal="true"
|
2026-02-04 15:19:29 +08:00
|
|
|
|
destroy-on-close
|
2026-02-04 17:19:29 +08:00
|
|
|
|
class="document-detail-drawer"
|
2026-02-04 15:19:29 +08:00
|
|
|
|
>
|
2026-02-04 17:19:29 +08:00
|
|
|
|
<div class="drawer-content">
|
2026-02-04 15:19:29 +08:00
|
|
|
|
<!-- 左侧:文档原文 -->
|
|
|
|
|
|
<div class="document-content">
|
2026-04-11 17:54:18 +08:00
|
|
|
|
<div class="content-header" style="display: flex; justify-content: space-between; align-items: flex-start">
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h2>{{ documentInfo.name }}</h2>
|
|
|
|
|
|
<div class="content-meta">Size:{{ formatFileSize(documentInfo.fileSize) }} Uploaded Time:{{ documentInfo.createdAt }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<a
|
|
|
|
|
|
href="#"
|
|
|
|
|
|
id="downloadLink"
|
|
|
|
|
|
style="
|
|
|
|
|
|
background-color: #f0f9eb;
|
|
|
|
|
|
color: #67c23a;
|
|
|
|
|
|
padding: 6px 12px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
border: 1px solid #e1f5dc;
|
|
|
|
|
|
margin-top: 4px;
|
|
|
|
|
|
"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
|
|
width="14"
|
|
|
|
|
|
height="14"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
stroke-linecap="round"
|
|
|
|
|
|
stroke-linejoin="round"
|
|
|
|
|
|
style="margin-right: 4px"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
|
|
|
|
<polyline points="7 10 12 15 17 10"></polyline>
|
|
|
|
|
|
<line x1="12" y1="15" x2="12" y2="3"></line>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
下载
|
|
|
|
|
|
</a>
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
<div class="content-body" v-loading="contentLoading">
|
2026-04-11 17:54:18 +08:00
|
|
|
|
<div class="document-text" v-html="documentContent"></div>
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<!-- 右侧:向量列表 -->
|
2026-02-04 15:19:29 +08:00
|
|
|
|
<div class="chunk-panel">
|
|
|
|
|
|
<div class="panel-header">
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<h3>向量列表</h3>
|
|
|
|
|
|
<div class="panel-subtitle">查看文档的向量信息。</div>
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</div>
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
<div class="panel-toolbar">
|
|
|
|
|
|
<div class="toolbar-actions">
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<el-input v-model="vectorSearch" placeholder="搜索" clearable size="small" style="width: 120px">
|
2026-02-04 15:19:29 +08:00
|
|
|
|
<template #prefix>
|
|
|
|
|
|
<el-icon><ele-Search /></el-icon>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<div class="vector-list" v-loading="vectorLoading">
|
|
|
|
|
|
<div class="vector-item" v-for="vector in vectorList" :key="vector.id">
|
|
|
|
|
|
<div class="vector-header">
|
|
|
|
|
|
<span class="vector-index">块 {{ vector.chunkIndex }}</span>
|
2026-04-16 14:49:33 +08:00
|
|
|
|
<span class="vector-status">状态: {{ vector.status ? '启用' : '禁用' }}</span>
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<span class="vector-vector-status">向量状态: {{ vector.vectorStatus === 1 ? '已生成' : '未生成' }}</span>
|
|
|
|
|
|
<el-switch v-model="vector.status" size="small" @change="(value: boolean) => onVectorStatusChange(vector, !value)" />
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</div>
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<div class="vector-content">
|
|
|
|
|
|
<span class="vector-text">{{ truncateText(vector.content, 150) }}</span>
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</div>
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<div class="vector-meta">
|
|
|
|
|
|
<span class="vector-hash">哈希: {{ vector.contentHash }}</span>
|
|
|
|
|
|
<span class="vector-time">创建时间: {{ vector.createdAt }}</span>
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<el-empty v-if="vectorList.length === 0 && !vectorLoading" description="暂无向量" :image-size="60" />
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</div>
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
<!-- 分页 -->
|
|
|
|
|
|
<div class="panel-footer">
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<span class="total-info">总共 {{ vectorTotal }} 条</span>
|
2026-02-04 15:19:29 +08:00
|
|
|
|
<el-pagination
|
2026-04-13 15:16:08 +08:00
|
|
|
|
v-model:current-page="vectorPage"
|
|
|
|
|
|
:page-size="vectorPageSize"
|
|
|
|
|
|
:total="vectorTotal"
|
2026-02-04 15:19:29 +08:00
|
|
|
|
layout="prev, pager, next"
|
|
|
|
|
|
small
|
2026-04-13 15:16:08 +08:00
|
|
|
|
@current-change="getVectorList"
|
2026-02-04 15:19:29 +08:00
|
|
|
|
/>
|
2026-04-13 15:16:08 +08:00
|
|
|
|
<el-select v-model="vectorPageSize" size="small" style="width: 80px" @change="getVectorList">
|
2026-02-04 15:19:29 +08:00
|
|
|
|
<el-option :value="10" label="10条/页" />
|
|
|
|
|
|
<el-option :value="20" label="20条/页" />
|
|
|
|
|
|
<el-option :value="50" label="50条/页" />
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-02-04 17:19:29 +08:00
|
|
|
|
</el-drawer>
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'documentDetailDialog',
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
2026-04-11 17:54:18 +08:00
|
|
|
|
import { ref, reactive, computed, watch, nextTick } from 'vue';
|
2026-02-04 15:19:29 +08:00
|
|
|
|
import { ElMessage } from 'element-plus';
|
2026-04-13 15:16:08 +08:00
|
|
|
|
import { listDocumentVectors, updateDocumentVector } from '/@/api/knowledge/document';
|
2026-02-04 15:19:29 +08:00
|
|
|
|
|
|
|
|
|
|
const props = defineProps<{
|
|
|
|
|
|
modelValue: boolean;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
knowledgeId: string;
|
|
|
|
|
|
knowledgeName: string;
|
2026-02-04 15:19:29 +08:00
|
|
|
|
document: any;
|
|
|
|
|
|
}>();
|
|
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['update:modelValue']);
|
|
|
|
|
|
|
|
|
|
|
|
const visible = computed({
|
|
|
|
|
|
get: () => props.modelValue,
|
|
|
|
|
|
set: (val) => emit('update:modelValue', val),
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 文档信息
|
|
|
|
|
|
const documentInfo = reactive({
|
|
|
|
|
|
id: '',
|
|
|
|
|
|
name: '',
|
|
|
|
|
|
fileType: '',
|
|
|
|
|
|
fileSize: 0,
|
|
|
|
|
|
createdAt: '',
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 文档内容
|
|
|
|
|
|
const documentContent = ref('');
|
|
|
|
|
|
const contentLoading = ref(false);
|
|
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
// 向量列表相关
|
|
|
|
|
|
const vectorLoading = ref(false);
|
|
|
|
|
|
const vectorList = ref<any[]>([]);
|
|
|
|
|
|
const vectorTotal = ref(0);
|
|
|
|
|
|
const vectorPage = ref(1);
|
|
|
|
|
|
const vectorPageSize = ref(50);
|
|
|
|
|
|
const vectorSearch = ref('');
|
|
|
|
|
|
const isInitializing = ref(true); // 初始化标志,用于防止加载时触发更新
|
2026-02-04 15:19:29 +08:00
|
|
|
|
|
|
|
|
|
|
// 格式化文件大小
|
|
|
|
|
|
const formatFileSize = (size: number) => {
|
|
|
|
|
|
if (!size) return '0 Bytes';
|
|
|
|
|
|
if (size < 1024) return size + ' Bytes';
|
|
|
|
|
|
if (size < 1024 * 1024) return (size / 1024).toFixed(0) + ' KB';
|
|
|
|
|
|
return (size / 1024 / 1024).toFixed(1) + ' MB';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 截断文本
|
|
|
|
|
|
const truncateText = (text: string, maxLength: number) => {
|
|
|
|
|
|
if (!text || text.length <= maxLength) return text;
|
|
|
|
|
|
return text.substring(0, maxLength) + '...';
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取文档详情
|
|
|
|
|
|
const getDocumentDetail = async () => {
|
|
|
|
|
|
contentLoading.value = true;
|
|
|
|
|
|
try {
|
2026-04-11 17:54:18 +08:00
|
|
|
|
// 使用实际的文档数据
|
2026-02-04 15:19:29 +08:00
|
|
|
|
documentInfo.id = props.document?.id || '';
|
2026-04-11 17:54:18 +08:00
|
|
|
|
documentInfo.name = props.document?.title || '未知文件';
|
|
|
|
|
|
documentInfo.fileSize = props.document?.fileSize || 0;
|
|
|
|
|
|
documentInfo.createdAt = props.document?.createdAt || '';
|
|
|
|
|
|
|
|
|
|
|
|
// 构建文件地址
|
|
|
|
|
|
const imgAddressPrefix = props.document?.imgAddressPrefix?.trim() || '';
|
|
|
|
|
|
const filePath = props.document?.filePath || '';
|
|
|
|
|
|
const fileUrl = imgAddressPrefix + filePath;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置下载链接
|
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
|
const downloadLink = document.getElementById('downloadLink');
|
|
|
|
|
|
if (downloadLink) {
|
|
|
|
|
|
downloadLink.setAttribute('href', fileUrl);
|
|
|
|
|
|
downloadLink.setAttribute('download', documentInfo.name);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试获取文件内容
|
|
|
|
|
|
let fileContent = '';
|
|
|
|
|
|
try {
|
|
|
|
|
|
const response = await fetch(fileUrl);
|
|
|
|
|
|
if (response.ok) {
|
|
|
|
|
|
fileContent = await response.text();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
fileContent = '无法加载文件内容';
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
fileContent = '无法加载文件内容';
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成文档内容,只包含文件内容
|
|
|
|
|
|
documentContent.value = `<pre style="background: #fafafa; padding: 16px; border-radius: 4px; border: 1px solid #ebeef5; margin: 0; white-space: pre-wrap; word-break: break-all; font-size: 14px; line-height: 1.5;">${fileContent}</pre>`;
|
2026-03-24 18:00:17 +08:00
|
|
|
|
} catch (_error) {
|
|
|
|
|
|
ElMessage.error('获取文档详情失败');
|
|
|
|
|
|
documentContent.value = '';
|
2026-02-04 15:19:29 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
contentLoading.value = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
// 获取向量列表
|
|
|
|
|
|
const getVectorList = async () => {
|
|
|
|
|
|
vectorLoading.value = true;
|
2026-02-04 15:19:29 +08:00
|
|
|
|
try {
|
2026-04-13 15:16:08 +08:00
|
|
|
|
const response = await listDocumentVectors({
|
|
|
|
|
|
documentId: props.document?.id,
|
|
|
|
|
|
datasetId: props.document?.datasetId,
|
|
|
|
|
|
pageNum: vectorPage.value,
|
|
|
|
|
|
pageSize: vectorPageSize.value,
|
|
|
|
|
|
});
|
2026-04-16 14:49:33 +08:00
|
|
|
|
// 深拷贝数据,避免v-model触发不必要的更新,并将status从数字转换为布尔类型
|
|
|
|
|
|
vectorList.value = (response.data?.list || []).map((item: any) => {
|
|
|
|
|
|
const clonedItem = JSON.parse(JSON.stringify(item));
|
|
|
|
|
|
// 将数字类型的status转换为布尔类型,以便正确绑定到el-switch
|
|
|
|
|
|
clonedItem.status = clonedItem.status === 1;
|
|
|
|
|
|
return clonedItem;
|
|
|
|
|
|
});
|
2026-04-13 15:16:08 +08:00
|
|
|
|
vectorTotal.value = response.data?.total || 0;
|
2026-03-24 18:00:17 +08:00
|
|
|
|
} catch (_error) {
|
2026-04-13 15:16:08 +08:00
|
|
|
|
ElMessage.error('获取向量列表失败');
|
|
|
|
|
|
vectorList.value = [];
|
|
|
|
|
|
vectorTotal.value = 0;
|
2026-02-04 15:19:29 +08:00
|
|
|
|
} finally {
|
2026-04-13 15:16:08 +08:00
|
|
|
|
vectorLoading.value = false;
|
|
|
|
|
|
// 初始化完成,允许状态更新
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
isInitializing.value = false;
|
|
|
|
|
|
}, 100);
|
2026-02-04 15:19:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
// 更新向量状态
|
|
|
|
|
|
const onVectorStatusChange = async (vector: any, oldValue: boolean) => {
|
|
|
|
|
|
// 初始化过程中不处理状态变化
|
|
|
|
|
|
if (isInitializing.value) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-02-04 15:19:29 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
// 计算新状态(ElSwitch的v-model是boolean,需要转换为数字)
|
|
|
|
|
|
const newStatus = vector.status ? 1 : 0;
|
|
|
|
|
|
const oldStatus = oldValue ? 1 : 0;
|
2026-02-04 15:19:29 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
// 只在状态真正改变时才调用API
|
|
|
|
|
|
if (newStatus !== oldStatus) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
await updateDocumentVector({
|
2026-04-13 18:02:00 +08:00
|
|
|
|
id: String(vector.id), // 确保id是字符串类型
|
2026-04-13 15:16:08 +08:00
|
|
|
|
status: newStatus,
|
|
|
|
|
|
});
|
|
|
|
|
|
ElMessage.success('更新成功');
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
ElMessage.error('更新失败');
|
|
|
|
|
|
// 恢复原始状态
|
|
|
|
|
|
vector.status = oldValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-02-04 15:19:29 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 监听弹窗打开
|
2026-03-30 17:35:05 +08:00
|
|
|
|
watch(
|
|
|
|
|
|
() => props.modelValue,
|
|
|
|
|
|
(val) => {
|
|
|
|
|
|
if (val && props.document) {
|
2026-04-13 15:16:08 +08:00
|
|
|
|
// 重置初始化标志
|
|
|
|
|
|
isInitializing.value = true;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
getDocumentDetail();
|
2026-04-13 15:16:08 +08:00
|
|
|
|
getVectorList();
|
2026-03-30 17:35:05 +08:00
|
|
|
|
}
|
2026-02-04 15:19:29 +08:00
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
);
|
2026-02-04 15:19:29 +08:00
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2026-02-04 17:19:29 +08:00
|
|
|
|
.document-detail-drawer {
|
|
|
|
|
|
:deep(.el-drawer__body) {
|
2026-02-04 15:19:29 +08:00
|
|
|
|
padding: 0;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-04 17:19:29 +08:00
|
|
|
|
.drawer-content {
|
2026-02-04 15:19:29 +08:00
|
|
|
|
display: flex;
|
2026-02-04 17:19:29 +08:00
|
|
|
|
height: 100%;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
// 左侧文档内容
|
|
|
|
|
|
.document-content {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
border-right: 1px solid #ebeef5;
|
|
|
|
|
|
overflow: hidden;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.content-header {
|
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
|
border-bottom: 1px solid #ebeef5;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
h2 {
|
|
|
|
|
|
margin: 0 0 8px 0;
|
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.content-meta {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.content-body {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
|
overflow: auto;
|
|
|
|
|
|
background: #fafafa;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.document-text {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
white-space: pre-wrap;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
// 右侧切片面板
|
|
|
|
|
|
.chunk-panel {
|
|
|
|
|
|
width: 420px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
background: #fff;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.panel-header {
|
|
|
|
|
|
padding: 16px 20px;
|
|
|
|
|
|
border-bottom: 1px solid #ebeef5;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
h3 {
|
|
|
|
|
|
margin: 0 0 4px 0;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.panel-subtitle {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.panel-toolbar {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
padding: 12px 20px;
|
|
|
|
|
|
border-bottom: 1px solid #ebeef5;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.toolbar-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
.vector-list {
|
2026-02-04 15:19:29 +08:00
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow: auto;
|
|
|
|
|
|
padding: 12px 20px;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
.vector-item {
|
2026-02-04 15:19:29 +08:00
|
|
|
|
display: flex;
|
2026-04-13 15:16:08 +08:00
|
|
|
|
flex-direction: column;
|
2026-02-04 15:19:29 +08:00
|
|
|
|
padding: 12px;
|
|
|
|
|
|
background: #f5f7fa;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
border: 1px solid #ebeef5;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
.vector-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #606266;
|
|
|
|
|
|
|
|
|
|
|
|
.vector-index {
|
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-switch {
|
|
|
|
|
|
margin-left: auto;
|
|
|
|
|
|
}
|
2026-02-04 15:19:29 +08:00
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
.vector-content {
|
|
|
|
|
|
margin-bottom: 8px;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
.vector-text {
|
2026-02-04 15:19:29 +08:00
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
color: #303133;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
word-break: break-all;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-04-13 15:16:08 +08:00
|
|
|
|
.vector-meta {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
|
|
|
|
|
|
.vector-hash {
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
max-width: 200px;
|
|
|
|
|
|
}
|
2026-02-04 15:19:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.panel-footer {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
gap: 12px;
|
|
|
|
|
|
padding: 12px 20px;
|
|
|
|
|
|
border-top: 1px solid #ebeef5;
|
2026-03-30 17:35:05 +08:00
|
|
|
|
|
2026-02-04 15:19:29 +08:00
|
|
|
|
.total-info {
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
color: #909399;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|