feat:新增dify接入知识库时更新文档嵌入参数的功能

This commit is contained in:
PingChuan
2025-12-04 17:47:44 +08:00
parent eca98fc540
commit dcdc21b90e
8 changed files with 392 additions and 96 deletions
@@ -1,8 +1,13 @@
import { message } from 'antd';
import { useCallback, useEffect, useState } from 'react';
import { updateDocumentWithSettings } from '~/api/dify-dataset/api/documentApi';
import { useCallback, useEffect, useRef, useState } from 'react';
import {
fetchUploadFileInfo,
downloadOriginalFile,
updateDocumentByFile,
fetchIndexingStatus,
} from '~/api/dify-dataset/api/documentApi';
import { fetchSegments } from '~/api/dify-dataset/api/segmentApi';
import type { Segment } from '~/api/dify-dataset/type';
import type { Segment, IndexingStatus } from '~/api/dify-dataset/type';
import type { Document } from '~/api/dify-dataset/type/documentTypes';
import type { DocumentDetailSegmentationSettings } from '~/types/dify-dataset-manager/document-detail';
import { DEFAULT_DOCUMENT_DETAIL_SETTINGS } from '~/types/dify-dataset-manager/document-detail';
@@ -22,6 +27,73 @@ export function useDocumentDetail(datasetId: string, document: Document | null)
// 保存状态
const [saving, setSaving] = useState(false);
// 处理状态(嵌入进度)
const [isProcessing, setIsProcessing] = useState(false);
const [indexingStatus, setIndexingStatus] = useState<IndexingStatus | null>(null);
const pollingTimerRef = useRef<ReturnType<typeof setInterval> | null>(null);
/**
* 停止轮询
*/
const stopPolling = useCallback(() => {
if (pollingTimerRef.current) {
clearInterval(pollingTimerRef.current);
pollingTimerRef.current = null;
}
}, []);
/**
* 轮询索引状态
*/
const pollIndexingStatus = useCallback(async (batch: string) => {
try {
const response = await fetchIndexingStatus(datasetId, batch);
const status = response.data?.[0];
if (status) {
setIndexingStatus(status.indexing_status);
if (status.indexing_status === 'completed') {
// 停止轮询
stopPolling();
setIsProcessing(false);
message.success('文档处理完成');
// 刷新分段预览
setPreviewLoading(true);
try {
const segmentResponse = await fetchSegments(datasetId, document?.id || '', 1, 50);
setPreviewSegments(segmentResponse.data || []);
setShowPreview(true);
} catch (err) {
console.error('刷新分段失败:', err);
} finally {
setPreviewLoading(false);
}
} else if (status.indexing_status === 'error') {
// 停止轮询
stopPolling();
setIsProcessing(false);
message.error(status.error || '处理失败');
}
}
} catch (err) {
console.error('获取索引状态失败:', err);
}
}, [datasetId, document?.id, stopPolling]);
/**
* 开始轮询
*/
const startPolling = useCallback((batch: string) => {
stopPolling();
pollingTimerRef.current = setInterval(() => {
pollIndexingStatus(batch);
}, 2000);
// 立即执行一次
pollIndexingStatus(batch);
}, [stopPolling, pollIndexingStatus]);
// 当文档变化时重置设置
useEffect(() => {
if (document) {
@@ -29,8 +101,18 @@ export function useDocumentDetail(datasetId: string, document: Document | null)
setSettings(DEFAULT_DOCUMENT_DETAIL_SETTINGS);
setPreviewSegments([]);
setShowPreview(false);
setIsProcessing(false);
setIndexingStatus(null);
stopPolling();
}
}, [document?.id]);
}, [document?.id, stopPolling]);
// 组件卸载时清理定时器
useEffect(() => {
return () => {
stopPolling();
};
}, [stopPolling]);
/**
* 更新设置
@@ -73,14 +155,27 @@ export function useDocumentDetail(datasetId: string, document: Document | null)
/**
* 保存并处理
* 流程:获取原始文件 → 下载 → 用新参数重新上传 → 轮询嵌入状态
*/
const handleSaveAndProcess = useCallback(async () => {
if (!document) return;
setIsProcessing(true);
setSaving(true);
setIndexingStatus('waiting');
try {
await updateDocumentWithSettings(datasetId, document.id, {
indexing_technique: 'high_quality',
// 1. 获取原始文件信息
message.loading({ content: '正在获取原始文件信息...', key: 'save-process' });
const uploadFileInfo = await fetchUploadFileInfo(datasetId, document.id);
// 2. 下载原始文件(通过代理路由)
message.loading({ content: '正在下载原始文件...', key: 'save-process' });
const file = await downloadOriginalFile(uploadFileInfo);
// 3. 用新参数重新上传
message.loading({ content: '正在应用新配置并重新处理...', key: 'save-process' });
const result = await updateDocumentByFile(datasetId, document.id, file, {
indexing_technique: settings.indexingTechnique,
process_rule: {
mode: 'custom',
rules: {
@@ -91,18 +186,25 @@ export function useDocumentDetail(datasetId: string, document: Document | null)
segmentation: {
separator: settings.separator.replace(/\\n/g, '\n'),
max_tokens: settings.maxTokens,
chunk_overlap: settings.chunkOverlap,
},
},
},
});
message.success('设置已保存,文档正在重新处理...');
message.success({ content: '文档正在处理中...', key: 'save-process' });
// 4. 开始轮询嵌入状态
startPolling(result.batch);
} catch (err: any) {
console.error('保存设置失败:', err);
message.error(err.message || '保存失败');
message.error({ content: err.message || '保存失败', key: 'save-process' });
setIsProcessing(false);
setIndexingStatus(null);
} finally {
setSaving(false);
}
}, [datasetId, document, settings]);
}, [datasetId, document, settings, startPolling]);
return {
// 状态
@@ -111,6 +213,8 @@ export function useDocumentDetail(datasetId: string, document: Document | null)
previewLoading,
showPreview,
saving,
isProcessing,
indexingStatus,
// 方法
updateSettings,