admin-vue3/src/views/ai/knowledge/document/form/ProcessStep.vue

147 lines
4.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div>
<!-- 文件处理列表 -->
<div class="mt-15px grid grid-cols-1 gap-2">
<div
v-for="(file, index) in modelValue.list"
:key="index"
class="flex items-center py-4px px-12px border-l-4 border-l-[#409eff] rounded-sm shadow-sm hover:bg-[#ecf5ff] transition-all duration-300"
>
<!-- 文件图标和名称 -->
<div class="flex items-center min-w-[200px] mr-10px">
<Icon icon="ep:document" class="mr-8px text-[#409eff]" />
<span class="text-[13px] text-[#303133] break-all">{{ file.name }}</span>
</div>
<!-- 处理进度 -->
<div class="flex-1">
<el-progress
:percentage="file.progress || 0"
:stroke-width="10"
:status="isProcessComplete(file) ? 'success' : ''"
/>
</div>
<!-- 分段数量 -->
<div class="ml-10px text-[13px] text-[#606266]">
分段数量:{{ file.count ? file.count : '-' }}
</div>
</div>
</div>
<!-- 底部完成按钮 -->
<div class="flex justify-end mt-20px">
<el-button
:type="allProcessComplete ? 'success' : 'primary'"
:disabled="!allProcessComplete"
@click="handleComplete"
>
完成
</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import { KnowledgeSegmentApi } from '@/api/ai/knowledge/segment'
const props = defineProps({
modelValue: {
type: Object,
required: true
}
})
const emit = defineEmits(['update:modelValue'])
const parent = inject('parent') as any
const pollingTimer = ref<number | null>(null) // 轮询定时器 ID用于跟踪和清除轮询进程
/** 判断文件处理是否完成 */
const isProcessComplete = (file) => {
return file.progress === 100
}
/** 判断所有文件是否都处理完成 */
const allProcessComplete = computed(() => {
return props.modelValue.list.every((file) => isProcessComplete(file))
})
/** 完成按钮点击事件处理 */
const handleComplete = () => {
if (parent?.exposed?.handleBack) {
parent.exposed.handleBack()
}
}
/** 获取文件处理进度 */
const getProcessList = async () => {
try {
// 1. 调用 API 获取处理进度
const documentIds = props.modelValue.list.filter((item) => item.id).map((item) => item.id)
if (documentIds.length === 0) {
return
}
const result = await KnowledgeSegmentApi.getKnowledgeSegmentProcessList(documentIds)
// 2.1更新进度
const updatedList = props.modelValue.list.map((file) => {
const processInfo = result.find((item) => item.documentId === file.id)
if (processInfo) {
// 计算进度百分比:已嵌入数量 / 总数量 * 100
const progress =
processInfo.embeddingCount && processInfo.count
? Math.floor((processInfo.embeddingCount / processInfo.count) * 100)
: 0
return {
...file,
progress: progress,
count: processInfo.count || 0
}
}
return file
})
// 2.2 更新数据
emit('update:modelValue', {
...props.modelValue,
list: updatedList
})
// 3. 如果未完成,继续轮询
if (!updatedList.every((file) => isProcessComplete(file))) {
pollingTimer.value = window.setTimeout(getProcessList, 3000)
}
} catch (error) {
// 出错后也继续轮询
console.error('获取处理进度失败:', error)
pollingTimer.value = window.setTimeout(getProcessList, 5000)
}
}
/** 组件挂载时开始轮询 */
onMounted(() => {
// 1. 初始化进度为 0
const initialList = props.modelValue.list.map((file) => ({
...file,
progress: 0
}))
emit('update:modelValue', {
...props.modelValue,
list: initialList
})
// 2. 开始轮询获取进度
getProcessList()
})
/** 组件卸载前清除轮询 */
onBeforeUnmount(() => {
// 1. 清除定时器
if (pollingTimer.value) {
clearTimeout(pollingTimer.value)
pollingTimer.value = null
}
})
</script>