style(web): translate Chinese comments to English in KnowledgeBase views
- Translate all Chinese comments to English in CreateDataset component - Translate Chinese comments in DocumentDetails, Private, and Share pages - Translate Chinese comments in all KnowledgeBase modal components (CreateContentModal, CreateDatasetModal, CreateFolderModal, etc.) - Translate Chinese comments in KnowledgeGraph, RecallTest, and related components - Translate Chinese comments in datasets and index files - Improve code readability and maintain consistency with existing English codebase - Ensure all inline comments and console logs use English for better maintainability
This commit is contained in:
@@ -24,7 +24,7 @@ const { TextArea } = Input;
|
||||
const radioWrapperBaseStyle: React.CSSProperties = {
|
||||
display: 'flex',
|
||||
alignItems: 'flex-start',
|
||||
columnGap: 14, // 点与文字更宽的间距
|
||||
columnGap: 14, // Wider gap between dot and text
|
||||
width: '100%',
|
||||
border: '1px solid #E5E5E5',
|
||||
borderRadius: 8,
|
||||
@@ -97,7 +97,7 @@ const CreateDataset = () => {
|
||||
() => [
|
||||
{ title: t('knowledgeBase.selectFile') },
|
||||
{ title: t('knowledgeBase.parameterSettings') },
|
||||
// { title: t('knowledgeBase.dataPreview') }, // 暂时隐藏第三步
|
||||
// { title: t('knowledgeBase.dataPreview') }, // Temporarily hide step 3
|
||||
{ title: t('knowledgeBase.confirmUpload') },
|
||||
],
|
||||
[t],
|
||||
@@ -105,27 +105,27 @@ const CreateDataset = () => {
|
||||
// 存储每个文件的 AbortController,用于取消上传
|
||||
const abortControllersRef = useRef<Map<string, AbortController>>(new Map());
|
||||
const uploadRef = useRef<{ fileList: UploadFile[]; clearFiles: () => void }>(null);
|
||||
console.log('上传文件',uploadRef.current?.fileList.length)
|
||||
console.log('Upload files', uploadRef.current?.fileList.length)
|
||||
const handleNext = async () => {
|
||||
// 暂时隐藏第三步:调整步骤索引(0->1->2 对应 选择文件->参数设置->确认上传)
|
||||
// Temporarily hide step 3: adjust step index (0->1->2 corresponds to select file->parameter settings->confirm upload)
|
||||
let nextStep = current + 1;
|
||||
|
||||
if(nextStep === 1 && source === 'local') {
|
||||
// 检查是否有文件已上传
|
||||
// Check if files have been uploaded
|
||||
if (rechunkFileIds.length === 0) {
|
||||
// 如果没有文件,提示用户先上传文件
|
||||
// If no files, prompt user to upload first
|
||||
Modal.warning({
|
||||
title: t('common.warning') || '提示',
|
||||
content: t('knowledgeBase.pleaseUploadFileFirst') || '请先上传文件',
|
||||
title: t('common.warning') || 'Warning',
|
||||
content: t('knowledgeBase.pleaseUploadFileFirst') || 'Please upload files first',
|
||||
});
|
||||
return; // 不进入下一步
|
||||
return; // Don't proceed to next step
|
||||
}
|
||||
}else if(nextStep === 1 && source === 'text'){
|
||||
try {
|
||||
const values = await form.validateFields();
|
||||
// setLoading(true);
|
||||
|
||||
// TODO: 这里需要调用相应的API来保存内容
|
||||
// TODO: Need to call corresponding API to save content here
|
||||
const params = {
|
||||
// ...values,
|
||||
kb_id: knowledgeBaseId,
|
||||
@@ -162,41 +162,41 @@ const CreateDataset = () => {
|
||||
})
|
||||
}
|
||||
|
||||
// 立即执行一次,加载文档列表用于预览(不自动返回)
|
||||
// Execute once immediately to load document list for preview (don't auto-return)
|
||||
pollDocumentStatus(false);
|
||||
}
|
||||
|
||||
// 限制最大步骤为 2(确认上传)
|
||||
// Limit max step to 2 (confirm upload)
|
||||
setCurrent(Math.min(nextStep, 2));
|
||||
};
|
||||
const handlePrev = () => setCurrent((c) => Math.max(c - 1, 0));
|
||||
|
||||
// 开始上传:触发文档解析并启动轮询
|
||||
// Start upload: trigger document parsing and start polling
|
||||
const handleStartUpload = () => {
|
||||
if (rechunkFileIds.length === 0) {
|
||||
Modal.warning({
|
||||
title: t('common.warning') || '提示',
|
||||
content: t('knowledgeBase.pleaseUploadFileFirst') || '请先上传文件',
|
||||
title: t('common.warning') || 'Warning',
|
||||
content: t('knowledgeBase.pleaseUploadFileFirst') || 'Please upload files first',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示确认弹框
|
||||
confirm({
|
||||
title: t('knowledgeBase.startUploadConfirmTitle') || '开始处理文档',
|
||||
content: t('knowledgeBase.startUploadConfirmContent') || '文档处理将在后台进行,您可以选择立即返回列表页或停留在此页面查看处理进度。',
|
||||
okText: t('knowledgeBase.returnToList') || '返回列表页',
|
||||
cancelText: t('knowledgeBase.stayOnPage') || '停留在此页',
|
||||
title: t('knowledgeBase.startUploadConfirmTitle') || 'Start processing documents',
|
||||
content: t('knowledgeBase.startUploadConfirmContent') || 'Document processing will proceed in the background. You can choose to return to the list page immediately or stay on this page to view processing progress.',
|
||||
okText: t('knowledgeBase.returnToList') || 'Return to list',
|
||||
cancelText: t('knowledgeBase.stayOnPage') || 'Stay on this page',
|
||||
onOk: () => {
|
||||
// 用户选择返回列表页 - 不显示 loading,直接跳转
|
||||
// User chose to return to list - don't show loading, navigate directly
|
||||
startProcessing(true);
|
||||
},
|
||||
onCancel: () => {
|
||||
// 用户选择停留在当前页 - 显示 loading 并开始轮询
|
||||
console.log('用户选择停留,开始显示 loading');
|
||||
// User chose to stay on current page - show loading and start polling
|
||||
console.log('User chose to stay, starting to show loading');
|
||||
setPollingLoading(true);
|
||||
|
||||
// 延迟一点时间让用户看到 loading 效果,然后开始处理
|
||||
// Delay a bit to let user see loading effect, then start processing
|
||||
setTimeout(() => {
|
||||
startProcessing(false);
|
||||
}, 100);
|
||||
@@ -204,25 +204,25 @@ const CreateDataset = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 实际开始处理的函数
|
||||
// Function to actually start processing
|
||||
const startProcessing = (autoReturnToList: boolean) => {
|
||||
// 触发文档解析
|
||||
// Trigger document parsing
|
||||
rechunkFileIds.map((id) => {
|
||||
parseDocument(id, {});
|
||||
});
|
||||
|
||||
if (autoReturnToList) {
|
||||
// 用户选择立即返回,直接跳转(不显示 loading)
|
||||
console.log('用户选择立即返回列表页');
|
||||
// User chose to return immediately, navigate directly (no loading shown)
|
||||
console.log('User chose to return to list page immediately');
|
||||
handleBack();
|
||||
} else {
|
||||
// 用户选择停留,启动轮询查看进度(loading 已在 onCancel 中设置)
|
||||
console.log('用户选择停留查看进度');
|
||||
// User chose to stay, start polling to view progress (loading already set in onCancel)
|
||||
console.log('User chose to stay and view progress');
|
||||
|
||||
// 立即执行一次轮询(启用自动返回)
|
||||
// Execute polling once immediately (enable auto-return)
|
||||
pollDocumentStatus(true);
|
||||
|
||||
// 然后每3秒执行一次(启用自动返回)
|
||||
// Then execute every 3 seconds (enable auto-return)
|
||||
pollingTimerRef.current = setInterval(() => {
|
||||
pollDocumentStatus(true);
|
||||
}, 3000);
|
||||
@@ -244,11 +244,11 @@ const CreateDataset = () => {
|
||||
|
||||
},
|
||||
onCancel: () => {
|
||||
console.log('取消删除');
|
||||
console.log('Delete cancelled');
|
||||
},
|
||||
});
|
||||
}
|
||||
// 表格列配置
|
||||
// Table column configuration
|
||||
const columns: ColumnsType = [
|
||||
{
|
||||
title: t('knowledgeBase.name'),
|
||||
@@ -261,7 +261,7 @@ const CreateDataset = () => {
|
||||
dataIndex: 'progress',
|
||||
key: 'progress',
|
||||
render: (value: number, record: any) => {
|
||||
// value >= 1 时完成,0~1 时显示进度条
|
||||
// When value >= 1 it's complete, when 0~1 show progress bar
|
||||
if (value >= 1) {
|
||||
return (
|
||||
<span className="rb:text-xs rb:border rb:border-[#DFE4ED] rb:bg-[#FBFDFF] rb:rounded rb:items-center rb:text-[#212332] rb:py-1 rb:px-2">
|
||||
@@ -270,7 +270,7 @@ const CreateDataset = () => {
|
||||
</span>
|
||||
);
|
||||
} else if (value >= 0 && value < 1) {
|
||||
// 处理中,显示进度条
|
||||
// Processing, show progress bar
|
||||
return (
|
||||
<div className="rb:flex rb:items-center rb:gap-2">
|
||||
<Progress
|
||||
@@ -286,7 +286,7 @@ const CreateDataset = () => {
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
// value = 0 或其他情况,显示待处理
|
||||
// value = 0 or other cases, show pending
|
||||
return (
|
||||
<span className="rb:text-xs rb:border rb:border-[#DFE4ED] rb:bg-[#FBFDFF] rb:rounded rb:items-center rb:text-[#212332] rb:py-1 rb:px-2">
|
||||
<span className="rb:inline-block rb:w-[5px] rb:h-[5px] rb:mr-2 rb:rounded-full" style={{ backgroundColor: '#FF8A4C' }}></span>
|
||||
@@ -304,7 +304,7 @@ const CreateDataset = () => {
|
||||
),
|
||||
},
|
||||
];
|
||||
// 检查媒体文件时长的辅助函数
|
||||
// Helper function to check media file duration
|
||||
const checkMediaDuration = (file: File): Promise<number> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = URL.createObjectURL(file);
|
||||
@@ -324,36 +324,36 @@ const CreateDataset = () => {
|
||||
});
|
||||
};
|
||||
|
||||
// 上传文件
|
||||
// Upload file
|
||||
const handleUpload = async (options: UploadRequestOption) => {
|
||||
const { file, onSuccess, onError, onProgress, filename = 'file' } = options;
|
||||
|
||||
// 创建 AbortController 用于取消上传
|
||||
// Create AbortController for cancelling upload
|
||||
const abortController = new AbortController();
|
||||
const fileUid = (file as any).uid;
|
||||
abortControllersRef.current.set(fileUid, abortController);
|
||||
|
||||
// 获取文件扩展名
|
||||
// Get file extension
|
||||
const fileExtension = (file as File).name.split('.').pop()?.toLowerCase();
|
||||
const mediaExtensions = ['mp3', 'mp4', 'mov', 'wav'];
|
||||
|
||||
// 如果是媒体文件,进行大小和时长检查
|
||||
// If media file, check size and duration
|
||||
if (fileExtension && mediaExtensions.includes(fileExtension)) {
|
||||
const fileSizeInMB = (file as File).size / (1024 * 1024);
|
||||
|
||||
// 检查文件大小(50MB限制)
|
||||
if (fileSizeInMB > 100) {
|
||||
messageApi.error(`${t('knowledgeBase.sizeLimitError')}:${fileSizeInMB.toFixed(2)}MB`);
|
||||
messageApi.error(`${t('knowledgeBase.sizeLimitError')}: ${fileSizeInMB.toFixed(2)}MB`);
|
||||
onError?.(new Error(`${t('knowledgeBase.fileSizeExceeds')}`));
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 检查媒体时长(150秒限制)
|
||||
// Check media duration (150 second limit)
|
||||
const duration = await checkMediaDuration(file as File);
|
||||
if (duration > 150) {
|
||||
messageApi.error(`${t('knowledgeBase.fileDurationLimitError')}:${Math.round(duration)}秒`);
|
||||
messageApi.error(`${t('knowledgeBase.fileDurationLimitError')}: ${Math.round(duration)}s`);
|
||||
onError?.(new Error(`${t('knowledgeBase.fileDurationExceeds')}`));
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
return;
|
||||
@@ -386,7 +386,7 @@ const CreateDataset = () => {
|
||||
},
|
||||
})
|
||||
.then((res: UploadFileResponse) => {
|
||||
// 上传成功,移除 AbortController
|
||||
// Upload successful, remove AbortController
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
|
||||
onSuccess?.(res, new XMLHttpRequest());
|
||||
@@ -399,12 +399,12 @@ const CreateDataset = () => {
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
// 移除 AbortController
|
||||
// Remove AbortController
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
|
||||
// 如果是用户主动取消,不显示错误信息
|
||||
// If user actively cancelled, don't show error message
|
||||
if (error.name === 'AbortError' || error.code === 'ERR_CANCELED') {
|
||||
console.log('上传已取消:', (file as File).name);
|
||||
console.log('Upload cancelled:', (file as File).name);
|
||||
return;
|
||||
}
|
||||
onError?.(error as Error);
|
||||
@@ -413,12 +413,12 @@ const CreateDataset = () => {
|
||||
|
||||
|
||||
// 轮询检查文档处理状态
|
||||
// autoReturn: 是否在所有文档完成时自动返回列表页
|
||||
// autoReturn: whether to automatically return to list page when all documents are completed
|
||||
const pollDocumentStatus = (autoReturn: boolean = false) => {
|
||||
console.log('开始轮询文档状态,当前 pollingLoading:', pollingLoading);
|
||||
console.log('Start polling document status, current pollingLoading:', pollingLoading);
|
||||
|
||||
if (!knowledgeBaseId || !parentId || rechunkFileIds.length === 0) {
|
||||
console.log('轮询条件不满足,退出');
|
||||
console.log('Polling conditions not met, exiting');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -436,10 +436,10 @@ const CreateDataset = () => {
|
||||
}
|
||||
|
||||
console.log('documents', documents);
|
||||
// 检查是否所有文档的 progress 都为 1
|
||||
// Check if all documents have progress of 1
|
||||
const allCompleted = documents.every((doc: KnowledgeBaseDocumentData) => doc.progress === 1);
|
||||
|
||||
console.log('轮询状态:', allCompleted);
|
||||
console.log('Polling status:', allCompleted);
|
||||
|
||||
// 检查是否所有文档都完成了
|
||||
// debugger
|
||||
@@ -455,23 +455,23 @@ const CreateDataset = () => {
|
||||
setPollingLoading(false);
|
||||
}, 1000);
|
||||
|
||||
// 只有在 autoReturn 为 true 时才自动返回
|
||||
// Only auto-return when autoReturn is true
|
||||
if (autoReturn) {
|
||||
// 延迟 2 秒后跳转,让用户看到完成状态
|
||||
console.log('所有文档处理完成,2秒后返回列表页');
|
||||
// Delay 2 seconds before navigating to let user see completion status
|
||||
console.log('All documents processed, returning to list page in 2 seconds');
|
||||
setTimeout(() => {
|
||||
handleBack();
|
||||
}, 2000);
|
||||
} else {
|
||||
console.log('所有文档处理完成,用户可手动操作');
|
||||
console.log('All documents processed, user can operate manually');
|
||||
}
|
||||
} else {
|
||||
// 如果还有文档在处理中,确保 loading 状态保持
|
||||
console.log('还有文档在处理中,保持 loading 状态');
|
||||
// If documents are still processing, keep loading state
|
||||
console.log('Documents still processing, maintaining loading state');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('轮询文档状态失败:', error);
|
||||
console.error('Failed to poll document status:', error);
|
||||
setPollingLoading(false);
|
||||
});
|
||||
};
|
||||
@@ -486,7 +486,7 @@ const CreateDataset = () => {
|
||||
},
|
||||
});
|
||||
} else {
|
||||
console.warn('缺少路由参数,无法返回');
|
||||
console.warn('Missing route parameters, unable to return');
|
||||
}
|
||||
};
|
||||
const handleChange = (value: number | null) =>{
|
||||
@@ -498,17 +498,17 @@ const CreateDataset = () => {
|
||||
const handleDeleteFile = async (fileId: string) => {
|
||||
try {
|
||||
await deleteDocument(fileId);
|
||||
// 删除成功,从 rechunkFileIds 中移除该 id
|
||||
// Delete successful, remove the id from rechunkFileIds
|
||||
setRechunkFileIds((prev) => prev.filter((id) => id !== fileId));
|
||||
console.log(`${t('common.deleteSuccess')}`);
|
||||
} catch (error) {
|
||||
messageApi.error(`${t('common.deleteFailed')}`);
|
||||
}
|
||||
};
|
||||
// 当从其他页面跳转过来且带有 fileIds 时,加载对应的文档数据
|
||||
// When navigating from other pages with fileIds, load corresponding document data
|
||||
// useEffect(() => {
|
||||
// if (initialFileIds.length > 0 && initialStepKey !== 'selectFile' && knowledgeBaseId && parentId) {
|
||||
// // 加载文档列表数据
|
||||
// // Load document list data
|
||||
// getDocumentList(knowledgeBaseId,{
|
||||
// document_ids: initialFileIds.join(','),
|
||||
// })
|
||||
@@ -517,12 +517,12 @@ const CreateDataset = () => {
|
||||
// setData(documents);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error('加载文档列表失败:', error);
|
||||
// console.error('Failed to load document list:', error);
|
||||
// });
|
||||
// }
|
||||
// }, []);
|
||||
|
||||
// 清理函数:组件卸载时清除定时器和 loading 状态
|
||||
// Cleanup function: clear timer and loading state when component unmounts
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (pollingTimerRef.current) {
|
||||
@@ -533,10 +533,10 @@ const CreateDataset = () => {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// 监听路由变化,确保在页面切换时清理状态
|
||||
// Watch for route changes, ensure state is cleaned up when page switches
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
// 页面卸载时清理状态
|
||||
// Clean up state when page unmounts
|
||||
if (pollingTimerRef.current) {
|
||||
clearInterval(pollingTimerRef.current);
|
||||
pollingTimerRef.current = null;
|
||||
@@ -574,7 +574,7 @@ const CreateDataset = () => {
|
||||
fileType={fileType}
|
||||
customRequest={handleUpload}
|
||||
onChange={(fileList) => {
|
||||
console.log('文件列表变化:', fileList);
|
||||
console.log('File list changed:', fileList);
|
||||
}}
|
||||
onRemove={async (file) => {
|
||||
// 如果文件正在上传,取消上传
|
||||
@@ -583,26 +583,26 @@ const CreateDataset = () => {
|
||||
if (abortController) {
|
||||
abortController.abort();
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
console.log('已取消上传:', (file as any).name);
|
||||
console.log('Upload cancelled:', (file as any).name);
|
||||
// 取消上传后直接返回 true,允许移除文件
|
||||
return true;
|
||||
}
|
||||
|
||||
// 只有当文件已经上传成功(有response.id)时,才删除服务器上的文件
|
||||
// Only delete server file when file upload was successful (has response.id)
|
||||
if (file.response?.id) {
|
||||
try {
|
||||
await deleteDocument(file.response.id);
|
||||
setRechunkFileIds(prev => prev.filter(id => id !== file.response.id));
|
||||
console.log('已删除服务器文件:', file.response.id);
|
||||
console.log('Server file deleted:', file.response.id);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('删除文件失败:', error);
|
||||
messageApi.error(t('common.deleteFailed') || '删除文件失败');
|
||||
return false; // 删除失败时不移除文件
|
||||
console.error('Failed to delete file:', error);
|
||||
messageApi.error(t('common.deleteFailed') || 'Failed to delete file');
|
||||
return false; // Don't remove file when deletion fails
|
||||
}
|
||||
}
|
||||
|
||||
// 其他情况(如上传失败的文件)也允许移除
|
||||
// Also allow removal in other cases (such as failed uploads)
|
||||
return true;
|
||||
}} />
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @Description: 文档详情
|
||||
/**
|
||||
* @Description: Document Details
|
||||
* @Version: 0.0.1
|
||||
* @Author: yujiangping
|
||||
* @Date: 2025-11-15 16:13:47
|
||||
@@ -57,28 +57,28 @@ const DocumentDetails: FC = () => {
|
||||
}
|
||||
}, [documentId]);
|
||||
|
||||
// 更新面包屑
|
||||
// Update breadcrumbs
|
||||
useEffect(() => {
|
||||
if (breadcrumbPath) {
|
||||
updateBreadcrumbs(breadcrumbPath);
|
||||
}
|
||||
}, [breadcrumbPath, updateBreadcrumbs]);
|
||||
|
||||
// 当文档加载完成且 progress === 1 时,加载分块列表
|
||||
// Load chunk list when document is loaded and progress === 1
|
||||
useEffect(() => {
|
||||
if (document && document.progress === 1 && !isManualRefreshRef.current) {
|
||||
ChunkList();
|
||||
}
|
||||
// 重置标志
|
||||
// Reset flag
|
||||
isManualRefreshRef.current = false;
|
||||
}, [document]);
|
||||
|
||||
// 监听 keywords 变化,重新搜索
|
||||
// Listen to keywords changes and re-search
|
||||
useEffect(() => {
|
||||
if (documentId && keywords && document?.progress === 1) {
|
||||
setPage(1); // 重置页码
|
||||
setChunkList([]); // 清空列表
|
||||
ChunkList(1, false); // 重新加载第一页
|
||||
setPage(1); // Reset page number
|
||||
setChunkList([]); // Clear list
|
||||
ChunkList(1, false); // Reload first page
|
||||
}
|
||||
}, [keywords]);
|
||||
|
||||
@@ -129,9 +129,9 @@ const DocumentDetails: FC = () => {
|
||||
const url = `${imagePath}/api/files/${response.file_id}`
|
||||
setFileUrl(url);
|
||||
setParserMode(response?.parser_config?.auto_questions || 0)
|
||||
// ChunkList 会在 useEffect 中根据 document.progress 自动调用
|
||||
// ChunkList will be called automatically in useEffect based on document.progress
|
||||
} catch (error) {
|
||||
console.error('获取文档详情失败:', error);
|
||||
console.error('Failed to fetch document details:', error);
|
||||
message.error(t('common.loadFailed') || '加载失败');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
@@ -140,12 +140,12 @@ const DocumentDetails: FC = () => {
|
||||
const ChunkList = async (pageNum: number = 1, append: boolean = false, force: boolean = false) => {
|
||||
if (!documentId) return;
|
||||
|
||||
// 如果不是强制刷新,且正在加载中,则跳过
|
||||
// Skip if not force refresh and already loading
|
||||
if (!force && chunkLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 只有当文档处理完成时才获取分块列表
|
||||
// Only fetch chunk list when document processing is complete
|
||||
if (document && document.progress !== 1) {
|
||||
return;
|
||||
}
|
||||
@@ -157,10 +157,10 @@ const DocumentDetails: FC = () => {
|
||||
keywords: keywords || undefined,
|
||||
page: pageNum,
|
||||
pagesize: 20,
|
||||
_t: force ? Date.now() : undefined, // 强制刷新时添加时间戳破坏缓存
|
||||
_t: force ? Date.now() : undefined, // Add timestamp to break cache when force refresh
|
||||
});
|
||||
|
||||
// 转换数据格式以匹配 RecallTestData
|
||||
// Convert data format to match RecallTestData
|
||||
const formattedChunks: RecallTestData[] = response.items.map((item: any) => ({
|
||||
page_content: item.page_content || item.content || '',
|
||||
vector: null,
|
||||
@@ -172,7 +172,7 @@ const DocumentDetails: FC = () => {
|
||||
document_id: item.metadata.document_id || documentId || '',
|
||||
knowledge_id: item.metadata.knowledge_id || knowledgeBaseId || '',
|
||||
sort_id: item.metadata.sort_id || item.id || 0,
|
||||
score: item.metadata.score || null, // chunk 列表没有相似度分数
|
||||
score: item.metadata.score || null, // Chunk list has no similarity score
|
||||
status: item.metadata.status,
|
||||
},
|
||||
children: null,
|
||||
@@ -186,7 +186,7 @@ const DocumentDetails: FC = () => {
|
||||
|
||||
setHasMore(response.page?.has_next ?? false);
|
||||
} catch (error) {
|
||||
console.error('获取文档详情失败:', error);
|
||||
console.error('Failed to fetch document details:', error);
|
||||
message.error(t('common.loadFailed') || '加载失败');
|
||||
} finally {
|
||||
setChunkLoading(false);
|
||||
@@ -201,17 +201,17 @@ const DocumentDetails: FC = () => {
|
||||
|
||||
const handleBack = () => {
|
||||
if (knowledgeBaseId && breadcrumbPath) {
|
||||
// 返回到知识库详情页,并传递面包屑信息以恢复状态
|
||||
// Return to knowledge base detail page and pass breadcrumb info to restore state
|
||||
const navigationState = {
|
||||
fromKnowledgeBaseList: true,
|
||||
knowledgeBaseFolderPath: breadcrumbPath.knowledgeBaseFolderPath,
|
||||
navigateToDocumentFolder: locationParentId,
|
||||
documentFolderPath: breadcrumbPath.documentFolderPath,
|
||||
timestamp: Date.now(), // 添加时间戳确保状态变化
|
||||
timestamp: Date.now(), // Add timestamp to ensure state change
|
||||
};
|
||||
navigate(`/knowledge-base/${knowledgeBaseId}/private`, { state: navigationState });
|
||||
} else if (knowledgeBaseId) {
|
||||
// 降级处理:直接跳转到知识库详情页
|
||||
// Fallback: Navigate directly to knowledge base detail page
|
||||
navigate(`/knowledge-base/${knowledgeBaseId}/private`);
|
||||
}
|
||||
};
|
||||
@@ -226,61 +226,61 @@ const DocumentDetails: FC = () => {
|
||||
insertModalRef.current?.handleOpen(documentId);
|
||||
};
|
||||
|
||||
// 处理插入/编辑内容
|
||||
// Handle insert/edit content
|
||||
const handleInsertContent = async (_docId: string, content: string, chunkId?: string): Promise<boolean> => {
|
||||
try {
|
||||
if (chunkId) {
|
||||
// 编辑模式:更新现有块
|
||||
// Edit mode: Update existing chunk
|
||||
const response = await updateDocumentChunk(knowledgeBaseId || '', documentId, chunkId, { content });
|
||||
|
||||
// 直接更新前端列表,不等待后端缓存刷新
|
||||
// Update frontend list directly without waiting for backend cache refresh
|
||||
setChunkList(prev => prev.map(item =>
|
||||
item.metadata?.doc_id === chunkId
|
||||
? { ...item, page_content: response.page_content || content }
|
||||
: item
|
||||
));
|
||||
|
||||
// 编辑模式返回特殊标记,告诉 InsertModal 不要调用 onSuccess
|
||||
// Edit mode returns special flag to tell InsertModal not to call onSuccess
|
||||
return true;
|
||||
} else {
|
||||
// 插入模式:创建新块
|
||||
// Insert mode: Create new chunk
|
||||
await createDocumentChunk(knowledgeBaseId || '', documentId, { content });
|
||||
return true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('操作失败:', error);
|
||||
console.error('Operation failed:', error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 处理点击文本块
|
||||
// Handle click on text chunk
|
||||
const handleChunkClick = (item: RecallTestData, index: number) => {
|
||||
if (!documentId) return;
|
||||
const chunkId = String(item.metadata?.doc_id || index);
|
||||
insertModalRef.current?.handleOpen(documentId, item.page_content, chunkId);
|
||||
};
|
||||
|
||||
// 插入成功后的回调(仅用于插入新块,编辑操作已在 handleInsertContent 中同步更新)
|
||||
// Callback after successful insert (only for inserting new chunks, edit operations are already updated synchronously in handleInsertContent)
|
||||
const handleInsertSuccess = () => {
|
||||
// 设置手动刷新标志,防止 useEffect 重复调用
|
||||
// Set manual refresh flag to prevent useEffect from calling repeatedly
|
||||
isManualRefreshRef.current = true;
|
||||
|
||||
// 重置页码
|
||||
// Reset page number
|
||||
setPage(1);
|
||||
|
||||
// 等待后端处理完成,然后重新加载数据(仅用于插入新块的情况)
|
||||
// Wait for backend processing to complete, then reload data (only for inserting new chunks)
|
||||
setTimeout(() => {
|
||||
ChunkList(1, false, true).then(() => {
|
||||
return fetchDocumentDetail();
|
||||
}).catch(err => {
|
||||
console.error('刷新失败:', err);
|
||||
console.error('Refresh failed:', err);
|
||||
});
|
||||
}, 1000);
|
||||
};
|
||||
const handleAdjustmentParameter = () =>{
|
||||
if (!knowledgeBaseId || !document) return;
|
||||
const targetFileId = document.id;
|
||||
// 优先使用从 location 传递的 parentId,其次使用 document.parent_id,最后使用 knowledgeBaseId
|
||||
// Prioritize parentId from location, then document.parent_id, finally knowledgeBaseId
|
||||
const parentId = locationParentId ?? document.parent_id ?? document.kb_id ?? knowledgeBaseId;
|
||||
|
||||
navigate(`/knowledge-base/${knowledgeBaseId}/create-dataset`, {
|
||||
@@ -317,7 +317,7 @@ const DocumentDetails: FC = () => {
|
||||
<img src={exitIcon} alt='exit' className='rb:w-4 rb:h-4' />
|
||||
<span className='rb:text-gray-500 rb:text-sm'>{t('common.exit')}</span>
|
||||
</div>
|
||||
{/* 文档预览 */}
|
||||
{/* Document preview */}
|
||||
{fileUrl && (
|
||||
<div className='rb:flex-1 rb:border rb:border-[#DFE4ED] rb:bg-white rb:rounded-xl rb:p-4 rb:overflow-hidden'>
|
||||
<h3 className="rb:text-sm rb:font-medium rb:mb-3">
|
||||
@@ -339,7 +339,7 @@ const DocumentDetails: FC = () => {
|
||||
|
||||
return (<>
|
||||
<div className="rb:flex rb:flex-col rb:h-full rb:p-4">
|
||||
{/* 头部 */}
|
||||
{/* Header */}
|
||||
<div className="rb:flex rb:flex-col rb:text-left rb:mb-6">
|
||||
<div className='rb:flex rb:items-center rb:justify-between'>
|
||||
<div className='rb:flex rb:items-center rb:gap-2 rb:mb-4 rb:cursor-pointer' onClick={handleBack}>
|
||||
@@ -366,9 +366,9 @@ const DocumentDetails: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 内容区域 */}
|
||||
{/* Content area */}
|
||||
<div className="rb:flex rb:h-full rb:gap-4 rb:flex-1 rb:overflow-hidden">
|
||||
{/* 左侧:文档信息 */}
|
||||
{/* Left: Document info */}
|
||||
<div className='rb:w-80 rb:h-full rb:flex rb:flex-col rb:gap-4 rb:overflow-hidden'>
|
||||
<div className='rb:border rb:border-[#DFE4ED] rb:bg-white rb:rounded-xl rb:p-4'>
|
||||
<InfoPanel
|
||||
@@ -381,7 +381,7 @@ const DocumentDetails: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 右侧:分块列表 */}
|
||||
{/* Right: Chunk list */}
|
||||
<div
|
||||
id="chunkScrollableDiv"
|
||||
className="rb:flex-1 rb:bg-white rb:rounded-lg rb:border rb:border-gray-200 rb:p-6 rb:overflow-y-auto"
|
||||
@@ -404,7 +404,7 @@ const DocumentDetails: FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 插入内容弹窗 */}
|
||||
{/* Insert content modal */}
|
||||
<InsertModal
|
||||
ref={insertModalRef}
|
||||
onInsert={handleInsertContent}
|
||||
|
||||
@@ -40,7 +40,7 @@ import KnowledgeGraphCard from '../components/KnowledgeGraphCard';
|
||||
import { useBreadcrumbManager, type BreadcrumbItem } from '@/hooks/useBreadcrumbManager';
|
||||
import './Private.css'
|
||||
const { confirm } = Modal
|
||||
// 树节点数据类型
|
||||
// Tree node data type
|
||||
|
||||
const Private: FC = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -73,9 +73,9 @@ const Private: FC = () => {
|
||||
const [isGraph, setIsGraph] = useState(false);
|
||||
const { updateBreadcrumbs } = useBreadcrumbManager({
|
||||
breadcrumbType: 'detail',
|
||||
// 不提供 onKnowledgeBaseMenuClick,让它使用默认的导航行为(返回列表页面)
|
||||
// Don't provide onKnowledgeBaseMenuClick, let it use default navigation behavior (return to list page)
|
||||
onKnowledgeBaseFolderClick: useCallback((folderId: string, folderPath: Array<{ id: string; name: string }>) => {
|
||||
// 点击文件夹面包屑时,导航到对应文件夹
|
||||
// Navigate to corresponding folder when clicking folder breadcrumb
|
||||
setParentId(folderId);
|
||||
setFolderPath(folderPath);
|
||||
setSelectedKeys([folderId]);
|
||||
@@ -84,7 +84,7 @@ const Private: FC = () => {
|
||||
parent_id: folderId
|
||||
});
|
||||
|
||||
// 确保query对象发生变化,触发表格刷新
|
||||
// Ensure query object changes to trigger table refresh
|
||||
setQuery({
|
||||
orderby: 'created_at',
|
||||
desc: true,
|
||||
@@ -92,10 +92,10 @@ const Private: FC = () => {
|
||||
_timestamp: Date.now()
|
||||
});
|
||||
|
||||
// 确保API URL正确设置
|
||||
// Ensure API URL is set correctly
|
||||
setTableApi(`/documents/${knowledgeBaseId}/documents`);
|
||||
|
||||
// 手动触发表格刷新,确保数据更新
|
||||
// Manually trigger table refresh to ensure data update
|
||||
setTimeout(() => {
|
||||
tableRef.current?.loadData();
|
||||
}, 100);
|
||||
@@ -108,7 +108,7 @@ const Private: FC = () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await getKnowledgeBaseDetail(id);
|
||||
// 将 KnowledgeBase 转换为 KnowledgeBaseListItem
|
||||
// Convert KnowledgeBase to KnowledgeBaseListItem
|
||||
const listItem = res as unknown as KnowledgeBaseListItem;
|
||||
setKnowledgeBase(listItem);
|
||||
} finally {
|
||||
@@ -122,7 +122,7 @@ const Private: FC = () => {
|
||||
setTableApi(url);
|
||||
fetchKnowledgeBaseDetail(knowledgeBaseId);
|
||||
|
||||
// 立即设置基础面包屑,确保不会显示其他页面的面包屑
|
||||
// Immediately set base breadcrumbs to ensure other page breadcrumbs are not displayed
|
||||
updateBreadcrumbs({
|
||||
knowledgeBaseFolderPath,
|
||||
knowledgeBase: {
|
||||
@@ -135,7 +135,7 @@ const Private: FC = () => {
|
||||
}
|
||||
}, [knowledgeBaseId]);
|
||||
|
||||
// 更新面包屑
|
||||
// Update breadcrumbs
|
||||
useEffect(() => {
|
||||
if (knowledgeBase) {
|
||||
updateBreadcrumbs({
|
||||
@@ -150,22 +150,22 @@ const Private: FC = () => {
|
||||
}
|
||||
}, [knowledgeBase, knowledgeBaseFolderPath, folderPath, updateBreadcrumbs]);
|
||||
|
||||
// 监听 tableApi 变化,自动刷新表格数据
|
||||
// Listen to tableApi changes and auto refresh table data
|
||||
useEffect(() => {
|
||||
if (tableApi) {
|
||||
tableRef.current?.loadData();
|
||||
}
|
||||
}, [tableApi]);
|
||||
|
||||
// 监听 query 变化,确保表格数据更新
|
||||
// Listen to query changes and ensure table data update
|
||||
useEffect(() => {
|
||||
if (tableApi && query._timestamp) {
|
||||
// 当 query 中有 _timestamp 时,说明是通过面包屑或其他方式触发的更新
|
||||
// When query has _timestamp, it means the update is triggered by breadcrumb or other means
|
||||
tableRef.current?.loadData();
|
||||
}
|
||||
}, [query._timestamp, tableApi]);
|
||||
|
||||
// 监听 location state 变化
|
||||
// Listen to location state changes
|
||||
useEffect(() => {
|
||||
const state = location.state as {
|
||||
refresh?: boolean;
|
||||
@@ -180,18 +180,18 @@ const Private: FC = () => {
|
||||
|
||||
if (state?.refresh) {
|
||||
tableRef.current?.loadData();
|
||||
// 清除 state,避免重复刷新
|
||||
// Clear state to avoid repeated refresh
|
||||
navigate(location.pathname, { replace: true, state: {} });
|
||||
}
|
||||
|
||||
// 如果是从知识库列表页跳转过来的,设置知识库文件夹路径
|
||||
// If navigated from knowledge base list page, set knowledge base folder path
|
||||
if (state?.fromKnowledgeBaseList && state?.knowledgeBaseFolderPath) {
|
||||
setKnowledgeBaseFolderPath(state.knowledgeBaseFolderPath);
|
||||
}
|
||||
|
||||
// 如果需要重置到根目录(回到初始状态)
|
||||
// If need to reset to root directory (return to initial state)
|
||||
if (state?.resetToRoot) {
|
||||
// 重置所有状态到初始状态,和页面初始化保持一致
|
||||
// Reset all states to initial state, consistent with page initialization
|
||||
setParentId(knowledgeBaseId);
|
||||
setFolderPath([]);
|
||||
setSelectedKeys([]);
|
||||
@@ -202,31 +202,31 @@ const Private: FC = () => {
|
||||
setQuery({
|
||||
orderby: 'created_at',
|
||||
desc: true,
|
||||
_timestamp: Date.now() // 添加时间戳确保query对象发生变化,触发API调用
|
||||
_timestamp: Date.now() // Add timestamp to ensure query object changes and trigger API call
|
||||
});
|
||||
|
||||
// 重新设置API URL
|
||||
// Reset API URL
|
||||
const rootUrl = `/documents/${knowledgeBaseId}/documents`;
|
||||
setTableApi(rootUrl);
|
||||
|
||||
// 清除自动展开路径
|
||||
// Clear auto expand path
|
||||
setAutoExpandPath([]);
|
||||
|
||||
// 刷新文件夹树 - 使用延迟确保状态重置完成后再刷新
|
||||
// Refresh folder tree - use delay to ensure state reset is complete before refresh
|
||||
setTimeout(() => {
|
||||
setFolderTreeRefreshKey((prev) => prev + 1);
|
||||
}, 100);
|
||||
|
||||
// 手动触发表格刷新,确保数据更新
|
||||
// Manually trigger table refresh to ensure data update
|
||||
setTimeout(() => {
|
||||
tableRef.current?.loadData();
|
||||
}, 200);
|
||||
|
||||
// 清除 state,避免重复处理
|
||||
// Clear state to avoid repeated processing
|
||||
navigate(location.pathname, { replace: true, state: {} });
|
||||
}
|
||||
|
||||
// 如果是从文档详情页返回,恢复文档文件夹路径
|
||||
// If returning from document details page, restore document folder path
|
||||
if (state?.navigateToDocumentFolder && state?.documentFolderPath) {
|
||||
setFolderPath(state.documentFolderPath);
|
||||
setParentId(state.navigateToDocumentFolder);
|
||||
@@ -242,25 +242,25 @@ const Private: FC = () => {
|
||||
setTableApi(`/documents/${knowledgeBaseId}/documents`);
|
||||
setSelectedKeys([state.navigateToDocumentFolder]);
|
||||
|
||||
// 设置自动展开路径,让FolderTree自动展开到对应位置
|
||||
// Set auto expand path to let FolderTree auto expand to corresponding position
|
||||
setAutoExpandPath(state.documentFolderPath);
|
||||
|
||||
// 手动触发表格刷新
|
||||
// Manually trigger table refresh
|
||||
setTimeout(() => {
|
||||
tableRef.current?.loadData();
|
||||
}, 100);
|
||||
|
||||
// 清除自动展开路径,避免重复触发(延迟清除,确保FolderTree处理完成)
|
||||
// Clear auto expand path to avoid repeated trigger (delayed clear to ensure FolderTree processing is complete)
|
||||
setTimeout(() => {
|
||||
setAutoExpandPath([]);
|
||||
}, 2000);
|
||||
}
|
||||
}, [location.state, knowledgeBaseId, navigate, location.pathname]);
|
||||
|
||||
// 处理树节点选择
|
||||
// Handle tree node selection
|
||||
const onSelect = (keys: React.Key[]) => {
|
||||
if (!keys.length) {
|
||||
// 如果没有选中任何节点,回到根目录(初始状态)
|
||||
// If no node is selected, return to root directory (initial state)
|
||||
setParentId(knowledgeBaseId);
|
||||
setFolder({
|
||||
kb_id: knowledgeBaseId ?? '',
|
||||
@@ -269,7 +269,7 @@ const Private: FC = () => {
|
||||
setQuery({
|
||||
orderby: 'created_at',
|
||||
desc: true,
|
||||
_timestamp: Date.now() // 添加时间戳确保query对象发生变化
|
||||
_timestamp: Date.now() // Add timestamp to ensure query object changes
|
||||
});
|
||||
setSelectedKeys([]);
|
||||
return;
|
||||
@@ -284,7 +284,7 @@ const Private: FC = () => {
|
||||
setQuery({
|
||||
...query,
|
||||
parent_id: String(keys[0]),
|
||||
_timestamp: Date.now() // 添加时间戳确保query对象发生变化
|
||||
_timestamp: Date.now() // Add timestamp to ensure query object changes
|
||||
})
|
||||
let url = `/documents/${knowledgeBaseId}/documents`;
|
||||
|
||||
@@ -294,14 +294,14 @@ const Private: FC = () => {
|
||||
setSelectedKeys(keys)
|
||||
};
|
||||
|
||||
// 处理文件夹路径变化
|
||||
// Handle folder path change
|
||||
const handleFolderPathChange = (path: Array<{ id: string; name: string }>) => {
|
||||
setFolderPath(path);
|
||||
};
|
||||
|
||||
// 处理树节点展开
|
||||
// Handle tree node expand
|
||||
const onExpand = (_expandedKeys: React.Key[], _info: any) => {
|
||||
// 展开节点时不需要特殊处理
|
||||
// No special handling needed when expanding nodes
|
||||
};
|
||||
// create / import list
|
||||
const createItems: MenuProps['items'] = [
|
||||
@@ -344,13 +344,13 @@ const Private: FC = () => {
|
||||
// createImageDataset?.current?.handleOpen(knowledgeBaseId || '', parentId || '')
|
||||
// },
|
||||
// },
|
||||
// 暂时未实现
|
||||
// Not implemented yet
|
||||
// {
|
||||
// key: '4',
|
||||
// icon: <img src={blankIcon} alt="blank" style={{ width: 16, height: 16 }} />,
|
||||
// label: t('knowledgeBase.blankDataset'),
|
||||
// onClick: () => {
|
||||
// handleCreate('folder'); // 传入 type: 'folder'
|
||||
// handleCreate('folder'); // Pass type: 'folder'
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
@@ -362,7 +362,7 @@ const Private: FC = () => {
|
||||
// icon: <img src={templateIcon} alt="import" style={{ width: 16, height: 16 }} />,
|
||||
// label: t('knowledgeBase.importTemplate'),
|
||||
// onClick: () => {
|
||||
// handleCreate('folder'); // 传入 type: 'folder'
|
||||
// handleCreate('folder'); // Pass type: 'folder'
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
@@ -370,17 +370,17 @@ const Private: FC = () => {
|
||||
// icon: <img src={backupIcon} alt="import" style={{ width: 16, height: 16 }} />,
|
||||
// label: t('knowledgeBase.importBackup'),
|
||||
// onClick: () => {
|
||||
// handleCreate('folder'); // 传入 type: 'folder'
|
||||
// handleCreate('folder'); // Pass type: 'folder'
|
||||
// },
|
||||
// },
|
||||
|
||||
];
|
||||
|
||||
// 处理开关
|
||||
// Handle switch
|
||||
const onChange = (checked: boolean) => {
|
||||
if (!knowledgeBase) return;
|
||||
|
||||
// 构造完整的更新数据,保留现有配置
|
||||
// Construct complete update data, keeping existing configuration
|
||||
const updateData: KnowledgeBaseFormData = {
|
||||
name: knowledgeBase.name,
|
||||
description: knowledgeBase.description,
|
||||
@@ -411,30 +411,30 @@ const Private: FC = () => {
|
||||
updateKnowledgeBase(knowledgeBaseId || '', updateData);
|
||||
console.log(`switch to ${checked}`);
|
||||
};
|
||||
// 处理搜索
|
||||
// Handle search
|
||||
const handleSearch = (value?: string) => {
|
||||
setQuery({ ...query, keywords: value })
|
||||
}
|
||||
|
||||
// 处理分享
|
||||
// Handle share
|
||||
const handleShare = () => {
|
||||
shareModalRef?.current?.handleOpen(knowledgeBaseId,knowledgeBase);
|
||||
}
|
||||
// 处理分享回调,接收选中的数据
|
||||
// Handle share callback, receive selected data
|
||||
const handleShareCallback = (selectedData: { checkedItems: any[], selectedItem: any | null }) => {
|
||||
console.log('选中的数据:', selectedData);
|
||||
// checkedItems: 所有 checked 为 true 的数据
|
||||
// selectedItem: 当前选中的项(curIndex 对应的数据)
|
||||
// 在这里处理分享逻辑
|
||||
console.log('Selected data:', selectedData);
|
||||
// checkedItems: All data with checked = true
|
||||
// selectedItem: Currently selected item (corresponding to curIndex)
|
||||
// Handle share logic here
|
||||
}
|
||||
const handleCreateDatasetCallback = (payload: { value: number; title: string; description: string }) => {
|
||||
console.log('创建数据集:', payload);
|
||||
console.log('Create dataset:', payload);
|
||||
}
|
||||
// 处理设置
|
||||
// Handle settings
|
||||
const handleSetting = () => {
|
||||
modalRef?.current?.handleOpen(knowledgeBase, '');
|
||||
}
|
||||
// 处理召回测试
|
||||
// Handle recall test
|
||||
const handleRecallTest = () => {
|
||||
recallTestDrawerRef?.current?.handleOpen(knowledgeBaseId);
|
||||
}
|
||||
@@ -443,7 +443,7 @@ const Private: FC = () => {
|
||||
const handelCreateOrImport = () => {
|
||||
|
||||
}
|
||||
// 生成下拉菜单项(根据当前 row)
|
||||
// Generate dropdown menu items (based on current row)
|
||||
const getOptMenuItems = (row: KnowledgeBaseListItem): MenuProps['items'] => [
|
||||
{
|
||||
key: '1',
|
||||
@@ -495,19 +495,19 @@ const Private: FC = () => {
|
||||
deleteDocument(item.id)
|
||||
.then(() => {
|
||||
messageApi.success(t('common.deleteSuccess'));
|
||||
// 刷新表格数据
|
||||
// Refresh table data
|
||||
tableRef.current?.loadData();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.log('删除失败', err);
|
||||
console.log('Delete failed', err);
|
||||
});
|
||||
},
|
||||
onCancel: () => {
|
||||
console.log('取消删除');
|
||||
console.log('Cancel delete');
|
||||
},
|
||||
});
|
||||
}
|
||||
// 表格列配置
|
||||
// Table column configuration
|
||||
const columns: ColumnsType = [
|
||||
{
|
||||
title: t('knowledgeBase.name'),
|
||||
@@ -524,7 +524,7 @@ const Private: FC = () => {
|
||||
state: {
|
||||
documentId: document.id,
|
||||
parentId: parentId ?? knowledgeBaseId,
|
||||
// 传递面包屑信息
|
||||
// Pass breadcrumb information
|
||||
breadcrumbPath: {
|
||||
knowledgeBaseFolderPath,
|
||||
knowledgeBase: {
|
||||
@@ -572,7 +572,7 @@ const Private: FC = () => {
|
||||
render: (value: string) => {
|
||||
if (!value) return '-';
|
||||
|
||||
// 解析日志格式,将 \n 转换为换行
|
||||
// Parse log format, convert \n to newline
|
||||
const formattedText = value.replace(/\\n/g, '\n');
|
||||
|
||||
return (
|
||||
@@ -634,25 +634,25 @@ const Private: FC = () => {
|
||||
),
|
||||
},
|
||||
];
|
||||
// 刷新列表数据
|
||||
// Refresh list data
|
||||
if (loading) {
|
||||
return <div>加载中...</div>;
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
|
||||
if (!knowledgeBase) {
|
||||
return <div>知识库不存在</div>;
|
||||
}
|
||||
const refreshDirectoryTree = async () => {
|
||||
// 先刷新知识库详情,确保数据是最新的
|
||||
// First refresh knowledge base details to ensure data is up-to-date
|
||||
if (knowledgeBase?.id) {
|
||||
await fetchKnowledgeBaseDetail(knowledgeBase.id);
|
||||
}
|
||||
// 添加短暂延迟,确保后端数据已经完全更新
|
||||
// Add short delay to ensure backend data is fully updated
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
// 然后刷新文件夹树
|
||||
// Then refresh folder tree
|
||||
setFolderTreeRefreshKey((prev) => prev + 1);
|
||||
|
||||
// 确保 folder 状态正确设置
|
||||
// Ensure folder state is set correctly
|
||||
if (!folder) {
|
||||
setFolder({
|
||||
kb_id: knowledgeBaseId ?? '',
|
||||
@@ -663,10 +663,10 @@ const Private: FC = () => {
|
||||
}
|
||||
const handleRootTreeLoad = (nodes: TreeNodeData[] | null) => {
|
||||
if (!nodes || nodes.length === 0) {
|
||||
// 如果没有节点,设置folder为null(这会隐藏FolderTree)
|
||||
// If no nodes, set folder to null (this will hide FolderTree)
|
||||
setFolder(null);
|
||||
} else {
|
||||
// 如果有节点且 folder 为 null,重新设置 folder
|
||||
// If there are nodes and folder is null, reset folder
|
||||
if (!folder) {
|
||||
setFolder({
|
||||
kb_id: knowledgeBaseId ?? '',
|
||||
@@ -687,7 +687,7 @@ const Private: FC = () => {
|
||||
}
|
||||
|
||||
const handleRefreshTable = () => {
|
||||
// 刷新表格数据
|
||||
// Refresh table data
|
||||
fetchKnowledgeBaseDetail(knowledgeBase.id)
|
||||
tableRef.current?.loadData();
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ const Share: FC = () => {
|
||||
|
||||
if (knowledgeBaseId) {
|
||||
fetchKnowledgeBaseDetail(knowledgeBaseId);
|
||||
// 打开召回测试组件
|
||||
// Open recall test component
|
||||
setTimeout(() => {
|
||||
console.log('Share.tsx - calling handleOpen with:', knowledgeBaseId);
|
||||
recallTestRef.current?.handleOpen(knowledgeBaseId);
|
||||
@@ -48,7 +48,7 @@ const Share: FC = () => {
|
||||
}
|
||||
}, [knowledgeBaseId]);
|
||||
|
||||
// 更新面包屑
|
||||
// Update breadcrumbs
|
||||
useEffect(() => {
|
||||
if (knowledgeBase) {
|
||||
updateBreadcrumbs({
|
||||
@@ -63,14 +63,14 @@ const Share: FC = () => {
|
||||
}
|
||||
}, [knowledgeBase, knowledgeBaseFolderPath, updateBreadcrumbs]);
|
||||
|
||||
// 监听 location state 变化
|
||||
// Listen to location state changes
|
||||
useEffect(() => {
|
||||
const state = location.state as {
|
||||
fromKnowledgeBaseList?: boolean;
|
||||
knowledgeBaseFolderPath?: BreadcrumbItem[];
|
||||
} | null;
|
||||
|
||||
// 如果是从知识库列表页跳转过来的,设置知识库文件夹路径
|
||||
// If navigated from knowledge base list page, set knowledge base folder path
|
||||
if (state?.fromKnowledgeBaseList && state?.knowledgeBaseFolderPath) {
|
||||
setKnowledgeBaseFolderPath(state.knowledgeBaseFolderPath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user