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:
@@ -41,7 +41,7 @@ const CreateContentModal = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
const values = await form.validateFields();
|
||||
setLoading(true);
|
||||
|
||||
// TODO: 这里需要调用相应的API来保存内容
|
||||
// TODO: Call appropriate API to save content
|
||||
const params = {
|
||||
// ...values,
|
||||
kb_id: kbId,
|
||||
@@ -55,7 +55,7 @@ const CreateContentModal = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
}
|
||||
handleClose();
|
||||
} catch (err) {
|
||||
console.error('创建内容失败:', err);
|
||||
console.error('Failed to create content:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
@@ -3,18 +3,18 @@ import { Button } from 'antd';
|
||||
import CreateContentModal from './CreateContentModal';
|
||||
import type { CreateContentModalRef } from '../types';
|
||||
|
||||
// 使用示例组件
|
||||
// Example usage component
|
||||
const CreateContentModalExample = () => {
|
||||
const createContentModalRef = useRef<CreateContentModalRef>(null);
|
||||
|
||||
const handleOpenModal = () => {
|
||||
// 打开弹窗,传入知识库ID和父级ID
|
||||
// Open modal, pass knowledge base ID and parent ID
|
||||
createContentModalRef.current?.handleOpen('kb_123', 'parent_456');
|
||||
};
|
||||
|
||||
const handleRefreshTable = () => {
|
||||
console.log('刷新表格数据');
|
||||
// 这里可以添加刷新表格的逻辑
|
||||
console.log('Refresh table data');
|
||||
// Add table refresh logic here
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @Description:
|
||||
/**
|
||||
* @Description: Create Dataset Modal
|
||||
* @Version: 0.0.1
|
||||
* @Author: yujiangping
|
||||
* @Date: 2025-11-10 18:52:55
|
||||
|
||||
@@ -13,7 +13,7 @@ const CreateFolderModal = forwardRef<CreateFolderModalRef,CreateFolderModalRefPr
|
||||
const [form] = Form.useForm<FolderFormData>();
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
// 封装取消方法,添加关闭弹窗逻辑
|
||||
// Close modal and reset state
|
||||
const handleClose = () => {
|
||||
setFolder({} as FolderFormData);
|
||||
form.resetFields();
|
||||
@@ -22,17 +22,16 @@ const CreateFolderModal = forwardRef<CreateFolderModalRef,CreateFolderModalRefPr
|
||||
};
|
||||
|
||||
const handleOpen = (folder?: FolderFormData | null) => {
|
||||
debugger
|
||||
if (folder) {
|
||||
setFolder(folder);
|
||||
// 设置表单值
|
||||
// Set form values
|
||||
form.setFieldsValue({
|
||||
folder_name: folder.folder_name,
|
||||
parent_id: folder.parent_id ?? '',
|
||||
kb_id: folder.kb_id ?? '',
|
||||
});
|
||||
} else {
|
||||
// 新建时,重置表单并设置默认值
|
||||
// Reset form and set default values for new folder
|
||||
form.resetFields();
|
||||
form.setFieldsValue({
|
||||
parent_id: '',
|
||||
@@ -41,7 +40,7 @@ const CreateFolderModal = forwardRef<CreateFolderModalRef,CreateFolderModalRefPr
|
||||
}
|
||||
setVisible(true);
|
||||
};
|
||||
// 封装保存方法,添加提交逻辑
|
||||
// Save form data and submit
|
||||
const handleSave = () => {
|
||||
form
|
||||
.validateFields({ validateOnly: true })
|
||||
@@ -74,13 +73,13 @@ const CreateFolderModal = forwardRef<CreateFolderModalRef,CreateFolderModalRefPr
|
||||
});
|
||||
}
|
||||
|
||||
// 暴露给父组件的方法
|
||||
// Expose methods to parent component
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
handleClose
|
||||
}));
|
||||
|
||||
// 根据 type 获取标题
|
||||
// Get modal title based on folder state
|
||||
const getTitle = () => {
|
||||
if (folder.id) {
|
||||
return t('common.edit') + ' ' + (folder.folder_name || '');
|
||||
|
||||
@@ -28,12 +28,12 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
const [parentId, setParentId] = useState<string>('');
|
||||
const [hasFiles, setHasFiles] = useState(false);
|
||||
const uploadRef = useRef<{ fileList: UploadFile[]; clearFiles: () => void }>(null);
|
||||
// 存储每个文件的 AbortController,用于取消上传
|
||||
// Store AbortController for each file to cancel upload
|
||||
const abortControllersRef = useRef<Map<string, AbortController>>(new Map());
|
||||
// const fileIds = [];
|
||||
|
||||
const handleClose = () => {
|
||||
// 取消所有正在进行的上传
|
||||
// Cancel all ongoing uploads
|
||||
abortControllersRef.current.forEach((controller) => {
|
||||
controller.abort();
|
||||
});
|
||||
@@ -69,7 +69,7 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
}
|
||||
const ids = fileList.map((file) => file.response?.id);
|
||||
handleChunking(kbId, parentId, ids)
|
||||
// // 上传所有图片
|
||||
// // Upload all images
|
||||
// const uploadPromises = fileList.map(async (file) => {
|
||||
// if (file.originFileObj) {
|
||||
// const formData = new FormData();
|
||||
@@ -91,7 +91,7 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
|
||||
handleClose();
|
||||
} catch (err) {
|
||||
console.error('创建图片数据集失败:', err);
|
||||
console.error('Failed to create image dataset:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
@@ -112,7 +112,7 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
}));
|
||||
// 检查媒体文件时长的辅助函数
|
||||
// Helper function to check media file duration
|
||||
const checkMediaDuration = (file: File): Promise<number> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const url = URL.createObjectURL(file);
|
||||
@@ -131,7 +131,7 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
media.src = url;
|
||||
});
|
||||
};
|
||||
// 删除已上传的文件
|
||||
// Delete uploaded file
|
||||
const handleDeleteFile = async (fileId: string) => {
|
||||
try {
|
||||
await deleteDocument(fileId);
|
||||
@@ -141,24 +141,24 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
}
|
||||
};
|
||||
|
||||
// 上传文件
|
||||
// Upload file
|
||||
const handleUpload = async (options: UploadRequestOption) => {
|
||||
const { file, onSuccess, onError, onProgress, filename = 'file' } = options;
|
||||
|
||||
// 创建 AbortController 用于取消上传
|
||||
// Create AbortController to cancel 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 it's a media file, check size and duration
|
||||
if (fileExtension && mediaExtensions.includes(fileExtension)) {
|
||||
const fileSizeInMB = (file as File).size / (50 * 1024);
|
||||
|
||||
// 检查文件大小(50MB限制)
|
||||
// Check file size (50MB limit)
|
||||
if (fileSizeInMB > 50) {
|
||||
messageApi.error(`${t('knowledgeBase.sizeLimitError')}:${fileSizeInMB.toFixed(2)}MB`);
|
||||
onError?.(new Error(`${t('knowledgeBase.fileSizeExceeds')}`));
|
||||
@@ -167,7 +167,7 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
}
|
||||
|
||||
try {
|
||||
// 检查媒体时长(150秒限制)
|
||||
// Check media duration (150 seconds limit)
|
||||
const duration = await checkMediaDuration(file as File);
|
||||
if (duration > 150) {
|
||||
messageApi.error(`${t('knowledgeBase.fileDurationLimitError')}:${Math.round(duration)}秒`);
|
||||
@@ -204,21 +204,21 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
},
|
||||
});
|
||||
|
||||
// 上传成功,移除 AbortController
|
||||
// Upload successful, remove AbortController
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
onSuccess?.(res, new XMLHttpRequest());
|
||||
|
||||
if (res?.id) {
|
||||
// 上传成功
|
||||
// Upload successful
|
||||
// fileIds.push(res.id)
|
||||
}
|
||||
} catch (error: any) {
|
||||
// 移除 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;
|
||||
}
|
||||
|
||||
@@ -259,11 +259,11 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
fileType={['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'mp3', 'mp4', 'mov', 'wav']}
|
||||
customRequest={handleUpload}
|
||||
onChange={(fileList) => {
|
||||
// 实时更新文件状态
|
||||
// Update file status in real-time
|
||||
setHasFiles(fileList.length > 0);
|
||||
}}
|
||||
onRemove={async (file) => {
|
||||
// 如果文件正在上传,取消上传
|
||||
// If file is uploading, cancel upload
|
||||
const fileUid = file.uid;
|
||||
const abortController = abortControllersRef.current.get(fileUid);
|
||||
if (abortController) {
|
||||
@@ -271,12 +271,12 @@ const CreateImageDataset = forwardRef<CreateSetModalRef, CreateSetMoealRefProps>
|
||||
abortControllersRef.current.delete(fileUid);
|
||||
}
|
||||
|
||||
// 如果文件已经上传成功,删除服务器上的文件
|
||||
// If file is already uploaded successfully, delete file on server
|
||||
if (file.response?.id) {
|
||||
await handleDeleteFile(file.response.id);
|
||||
}
|
||||
|
||||
return true; // 允许移除文件
|
||||
return true; // Allow file removal
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
@@ -15,7 +15,7 @@ import RbModal from '@/components/RbModal'
|
||||
const { TextArea } = Input;
|
||||
const { confirm } = Modal
|
||||
|
||||
// 全局模型数据常量
|
||||
// Global model data constant
|
||||
let models: any = null;
|
||||
|
||||
const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
@@ -33,9 +33,9 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
const [activeTab, setActiveTab] = useState('basic');
|
||||
const [generatingEntityTypes, setGeneratingEntityTypes] = useState(false);
|
||||
const [isRebuildMode, setIsRebuildMode] = useState(false);
|
||||
const [originalType, setOriginalType] = useState<string>(''); // 保存原始的 type 参数
|
||||
const [originalType, setOriginalType] = useState<string>(''); // Save original type parameter
|
||||
|
||||
// 监听 parser_config.graphrag 相关字段的变化
|
||||
// Watch for changes to parser_config.graphrag related fields
|
||||
const parserConfig = Form.useWatch('parser_config', form);
|
||||
const graphragConfig = parserConfig?.graphrag;
|
||||
const enableKnowledgeGraph = graphragConfig?.use_graphrag || false;
|
||||
@@ -43,30 +43,30 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
const entityNormalization = graphragConfig?.resolution || false;
|
||||
const communityReportGeneration = graphragConfig?.community || false;
|
||||
|
||||
// 封装取消方法,添加关闭弹窗逻辑
|
||||
// Encapsulate cancel method, add close modal logic
|
||||
const handleClose = () => {
|
||||
setDatasets(null);
|
||||
form.resetFields();
|
||||
setLoading(false);
|
||||
setActiveTab('basic');
|
||||
setIsRebuildMode(false); // 重置重建模式标识
|
||||
setOriginalType(''); // 重置原始 type
|
||||
setIsRebuildMode(false); // Reset rebuild mode flag
|
||||
setOriginalType(''); // Reset original type
|
||||
setVisible(false);
|
||||
};
|
||||
|
||||
// 生成实体类型的函数
|
||||
// Generate entity types function
|
||||
const generateEntityTypes = async () => {
|
||||
const sceneName = form.getFieldValue(['parser_config', 'graphrag', 'scene_name']);
|
||||
if (!sceneName) {
|
||||
// 可以添加提示用户输入场景名称
|
||||
// Can add prompt for user to enter scenario name
|
||||
messageApi.error(t('knowledgeBase.enterScenarioName'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查是否选择了 LLM 模型
|
||||
// Check if LLM model is selected
|
||||
const llmId = form.getFieldValue('llm_id');
|
||||
if (!llmId) {
|
||||
// 跳转到基础配置页
|
||||
// Navigate to basic configuration page
|
||||
setActiveTab('basic');
|
||||
messageApi.error(t('knowledgeBase.pleaseSelectLLMModel'));
|
||||
return;
|
||||
@@ -74,7 +74,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
|
||||
setGeneratingEntityTypes(true);
|
||||
try {
|
||||
// 这里应该调用实际的API接口
|
||||
// Call the actual API interface here
|
||||
// const user = JSON.parse(localStorage.getItem('user') as any);
|
||||
//datasets?.id || datasets?.parent_id || user?.current_workspace_id,
|
||||
const params = {
|
||||
@@ -82,17 +82,17 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
llm_id: llmId
|
||||
};
|
||||
const response = await getKnowledgeGraphEntityTypes(params);
|
||||
// 模拟API调用
|
||||
// Simulate API call
|
||||
// await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
// 处理API响应数据
|
||||
console.log('API Response:', response); // 调试日志
|
||||
// Process API response data
|
||||
console.log('API Response:', response); // Debug log
|
||||
|
||||
// 检查响应结构 - API直接返回字符串
|
||||
// Check response structure - API returns string directly
|
||||
if (response && typeof response === 'string' && response.trim()) {
|
||||
// 将逗号分隔的字符串转换为换行分隔的格式以便在TextArea中显示
|
||||
// Convert comma-separated string to newline-separated format for TextArea display
|
||||
const entityTypesString = response.replace(/,\s*/g, '\n');
|
||||
console.log('Converted entity types:', entityTypesString); // 调试日志
|
||||
console.log('Converted entity types:', entityTypesString); // Debug log
|
||||
|
||||
const currentGraphrag = form.getFieldValue(['parser_config', 'graphrag']) || {};
|
||||
const updatedGraphrag = {
|
||||
@@ -100,22 +100,22 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
entity_types: entityTypesString
|
||||
};
|
||||
|
||||
console.log('Updating form with:', updatedGraphrag); // 调试日志
|
||||
console.log('Updating form with:', updatedGraphrag); // Debug log
|
||||
|
||||
// 使用更直接的方式更新表单字段
|
||||
// Use more direct way to update form field
|
||||
form.setFieldValue(['parser_config', 'graphrag', 'entity_types'], entityTypesString);
|
||||
|
||||
// 强制触发表单重新渲染
|
||||
// Force trigger form re-render
|
||||
form.validateFields([['parser_config', 'graphrag', 'entity_types']]);
|
||||
|
||||
// 额外的强制更新机制
|
||||
// Additional forced update mechanism
|
||||
setTimeout(() => {
|
||||
form.setFieldValue(['parser_config', 'graphrag', 'entity_types'], entityTypesString);
|
||||
}, 100);
|
||||
|
||||
messageApi.success(t('knowledgeBase.generateEntityTypesSuccess'));
|
||||
} else {
|
||||
messageApi.error(t('knowledgeBase.generateEntityTypesFailed') + ':' + t('knowledgeBase.unknownError'));
|
||||
messageApi.error(t('knowledgeBase.generateEntityTypesFailed') + ': ' + t('knowledgeBase.unknownError'));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(t('knowledgeBase.generateEntityTypesFailed') + ':', error);
|
||||
@@ -143,7 +143,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
};
|
||||
|
||||
const fetchModelLists = async (types: string[]) => {
|
||||
// 如果还没有获取过全部模型数据,则获取一次
|
||||
// If model data hasn't been fetched yet, fetch it once
|
||||
if (!models) {
|
||||
try {
|
||||
models = await getModelList({ page: 1, pagesize: 100 });
|
||||
@@ -153,7 +153,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
}
|
||||
}
|
||||
|
||||
// 从全部模型数据中过滤出需要的类型
|
||||
// Filter out the required types from all model data
|
||||
const typesToFetch = types.includes('llm') ? [...types, 'chat'] : types;
|
||||
const next: Record<string, { label: string; value: string }[]> = {};
|
||||
|
||||
@@ -165,7 +165,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
|
||||
setModelOptionsByType(next);
|
||||
|
||||
// 如果不是编辑模式,为每个类型的下拉框设置默认值为第一条数据
|
||||
// If not in edit mode, set default value to first item for each type dropdown
|
||||
if (!datasets?.id) {
|
||||
const defaultValues: Record<string, string> = {};
|
||||
types.forEach((tp) => {
|
||||
@@ -174,7 +174,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
? [...(next['llm'] || []), ...(next['chat'] || [])]
|
||||
: next[tp] || [];
|
||||
|
||||
// 如果有选项且当前字段没有值,设置第一个选项为默认值
|
||||
// If there are options and current field has no value, set first option as default
|
||||
if (options.length > 0 && !form.getFieldValue(fieldKey)) {
|
||||
defaultValues[fieldKey] = options[0].value;
|
||||
}
|
||||
@@ -204,7 +204,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
status: record.status,
|
||||
};
|
||||
|
||||
// 处理 parser_config 配置数据,如果没有则设置默认值
|
||||
// Process parser_config data, set default values if not present
|
||||
baseValues.parser_config = record.parser_config || {
|
||||
graphrag: {
|
||||
use_graphrag: false,
|
||||
@@ -216,13 +216,13 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
}
|
||||
};
|
||||
|
||||
// 如果存在 entity_types,转换为换行分隔格式用于 TextArea 显示
|
||||
// If entity_types exists, convert to newline-separated format for TextArea display
|
||||
if (baseValues.parser_config.graphrag.entity_types) {
|
||||
if (Array.isArray(baseValues.parser_config.graphrag.entity_types)) {
|
||||
// 如果是数组格式,转换为换行分隔字符串
|
||||
// If array format, convert to newline-separated string
|
||||
(baseValues.parser_config.graphrag as any).entity_types = baseValues.parser_config.graphrag.entity_types.join('\n');
|
||||
} else if (typeof baseValues.parser_config.graphrag.entity_types === 'string') {
|
||||
// 如果是逗号分隔字符串格式,转换为换行分隔字符串(兼容旧数据)
|
||||
// If comma-separated string format, convert to newline-separated string (compatible with old data)
|
||||
(baseValues.parser_config.graphrag as any).entity_types = (baseValues.parser_config.graphrag.entity_types as string).replace(/,\s*/g, '\n');
|
||||
}
|
||||
}
|
||||
@@ -249,13 +249,13 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
const handleOpen = (record?: KnowledgeBaseListItem | null, type?: string) => {
|
||||
setDatasets(record || null);
|
||||
|
||||
// 如果是重建模式,使用记录的实际类型,否则使用传入的类型
|
||||
// If rebuild mode, use record's actual type, otherwise use passed type
|
||||
const actualType = type === 'rebuild' ? (record?.type || 'General') : (type || currentType);
|
||||
setCurrentType(actualType as any);
|
||||
setIsRebuildMode(type === 'rebuild'); // 设置重建模式标识
|
||||
setOriginalType(type || ''); // 保存原始的 type 参数
|
||||
setIsRebuildMode(type === 'rebuild'); // Set rebuild mode flag
|
||||
setOriginalType(type || ''); // Save original type parameter
|
||||
|
||||
// 如果是重建模式,默认切换到知识图谱标签页
|
||||
// If rebuild mode, default to knowledge graph tab
|
||||
if (type === 'rebuild') {
|
||||
setActiveTab('knowledgeGraph');
|
||||
} else {
|
||||
@@ -285,13 +285,13 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
setDynamicModelFields(datasets, modelTypeList);
|
||||
}, [visible, datasets, currentType, modelTypeList]);
|
||||
|
||||
// 封装保存方法,添加提交逻辑
|
||||
// Encapsulate save method, add submit logic
|
||||
const handleSave = () => {
|
||||
// 获取当前表单中的知识图谱开启状态
|
||||
// Get current knowledge graph enabled status from form
|
||||
const currentFormValues = form.getFieldsValue();
|
||||
const isGraphragEnabled = currentFormValues?.parser_config?.graphrag?.use_graphrag || false;
|
||||
|
||||
// 如果原始 type 是 'rebuild' 并且知识图谱开启为true,显示确认弹框
|
||||
// If original type is 'rebuild' and knowledge graph is enabled, show confirmation dialog
|
||||
if (originalType === 'rebuild' && isGraphragEnabled) {
|
||||
confirm({
|
||||
title: t('knowledgeBase.rebuildConfirmTitle'),
|
||||
@@ -302,11 +302,11 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
await rebuildKnowledgeGraph(datasets?.id || '')
|
||||
},
|
||||
onCancel: () => {
|
||||
// 用户取消,不执行任何操作
|
||||
// User cancelled, no action taken
|
||||
},
|
||||
});
|
||||
} else {
|
||||
// 非重建模式或知识图谱未开启,直接保存
|
||||
// Non-rebuild mode or knowledge graph not enabled, save directly
|
||||
performSave();
|
||||
}
|
||||
};
|
||||
@@ -318,7 +318,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
messageApi.error(t('knowledgeBase.deleteGraphFailed'))
|
||||
}
|
||||
};
|
||||
// 实际的保存逻辑
|
||||
// Actual save logic
|
||||
const performSave = () => {
|
||||
form
|
||||
.validateFields()
|
||||
@@ -326,7 +326,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
setLoading(true)
|
||||
const formValues = form.getFieldsValue();
|
||||
|
||||
// 处理 entity_types 格式转换:从换行分隔字符串转换为字符串数组
|
||||
// Process entity_types format conversion: from newline-separated string to string array
|
||||
if (formValues.parser_config && formValues.parser_config.graphrag && formValues.parser_config.graphrag.entity_types) {
|
||||
const entityTypesString = formValues.parser_config.graphrag.entity_types as any as string;
|
||||
const entityTypesArray = entityTypesString
|
||||
@@ -336,7 +336,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
formValues.parser_config.graphrag.entity_types = entityTypesArray;
|
||||
}
|
||||
|
||||
// 确保保存时使用正确的类型(不是 'rebuild')
|
||||
// Ensure correct type is used when saving (not 'rebuild')
|
||||
const saveType = originalType === 'rebuild' ? currentType : (formValues.type || currentType);
|
||||
|
||||
const payload: KnowledgeBaseFormData = {
|
||||
@@ -346,7 +346,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
parent_id: datasets?.parent_id || undefined,
|
||||
};
|
||||
|
||||
console.log('Saving payload:', payload); // 调试日志
|
||||
console.log('Saving payload:', payload); // Debug log
|
||||
|
||||
const submit = datasets?.id
|
||||
? updateKnowledgeBase(datasets.id, payload)
|
||||
@@ -367,32 +367,32 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
});
|
||||
}
|
||||
const handleChange = (_value: string, tp: string) => {
|
||||
// 只在编辑模式且类型为 embedding 时触发提示
|
||||
// Only trigger prompt in edit mode and when type is embedding
|
||||
if (datasets?.id && tp.toLowerCase() === 'embedding') {
|
||||
const fieldKey = typeToFieldKey(tp);
|
||||
// 从原始 datasets 对象中获取之前的值
|
||||
// Get previous value from original datasets object
|
||||
const previousValue = (datasets as any)[fieldKey];
|
||||
|
||||
confirm({
|
||||
title: t('common.updateWarning'),
|
||||
content: t('knowledgeBase.updateEmbeddingContent'),
|
||||
onOk: () => {
|
||||
// 确定时什么也不做,保持新值
|
||||
// Do nothing on confirm, keep new value
|
||||
},
|
||||
onCancel: () => {
|
||||
// 取消时恢复之前的值
|
||||
// Restore previous value on cancel
|
||||
form.setFieldsValue({ [fieldKey]: previousValue } as any);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
// 暴露给父组件的方法
|
||||
// Methods exposed to parent component
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
handleClose
|
||||
}));
|
||||
|
||||
// 根据 type 获取标题
|
||||
// Get title based on type
|
||||
const getTitle = () => {
|
||||
if (isRebuildMode) {
|
||||
return t('knowledgeBase.rebuildGraph') + ' - ' + (datasets?.name || '');
|
||||
@@ -408,7 +408,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
|
||||
const dynamicTypeList = useMemo(() => modelTypeList.filter((tp) => (modelOptionsByType[tp] || []).length), [modelTypeList, modelOptionsByType]);
|
||||
|
||||
// 基础配置表单内容
|
||||
// Basic configuration form content
|
||||
const renderBasicConfig = () => (
|
||||
<>
|
||||
{!datasets?.id && (
|
||||
@@ -426,7 +426,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
|
||||
{currentType !== 'Folder' && dynamicTypeList.map((tp) => {
|
||||
const fieldKey = typeToFieldKey(tp);
|
||||
// 当 tp 为 'llm' 时,合并 llm 和 chat 的选项
|
||||
// When tp is 'llm', merge llm and chat options
|
||||
const options = tp.toLowerCase() === 'llm'
|
||||
? [...(modelOptionsByType['llm'] || []), ...(modelOptionsByType['chat'] || [])]
|
||||
: modelOptionsByType[tp] || [];
|
||||
@@ -451,7 +451,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
</>
|
||||
);
|
||||
|
||||
// 知识图谱配置表单内容
|
||||
// Knowledge graph configuration form content
|
||||
const renderKnowledgeGraphConfig = () => (
|
||||
<>
|
||||
<div className={`rb:flex rb:w-full rb:items-center rb:p-4 rb:border-1 rb:rounded-lg rb:mb-4 ${
|
||||
@@ -482,7 +482,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
<div className='rb:text-[#212332] rb:text-base rb:font-medium rb:mb-4'>
|
||||
{t('knowledgeBase.graphConfig')}
|
||||
</div>
|
||||
{/* 场景名称 */}
|
||||
{/* Scene name */}
|
||||
<div className='rb:flex rb:items-center rb:gap-2'>
|
||||
<Form.Item
|
||||
name={['parser_config', 'graphrag', 'scene_name']}
|
||||
@@ -506,7 +506,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
</div>
|
||||
|
||||
|
||||
{/* 实体类型 */}
|
||||
{/* Entity types */}
|
||||
<Form.Item
|
||||
name={['parser_config', 'graphrag', 'entity_types']}
|
||||
label={t('knowledgeBase.entityTypes')}
|
||||
@@ -517,7 +517,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{/* 实体归一化 */}
|
||||
{/* Entity normalization */}
|
||||
<div className={`rb:flex rb:w-full rb:gap-2 rb:items-center rb:p-4 rb:border-1 rb:rounded-lg rb:mb-4 ${
|
||||
entityNormalization
|
||||
? 'rb:border-[#155EEF] rb:bg-[rgba(21,94,239,0.06)]'
|
||||
@@ -541,7 +541,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
</div>
|
||||
|
||||
|
||||
{/* 实体方法 */}
|
||||
{/* Entity method */}
|
||||
<Form.Item
|
||||
name={['parser_config', 'graphrag', 'method']}
|
||||
label={t('knowledgeBase.entityMethod')}
|
||||
@@ -553,7 +553,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
|
||||
{/* 社区报告生成 */}
|
||||
{/* Community report generation */}
|
||||
<div className={`rb:flex rb:w-full rb:gap-2 rb:items-center rb:p-4 rb:border-1 rb:rounded-lg rb:mb-4 ${
|
||||
communityReportGeneration
|
||||
? 'rb:border-[#155EEF] rb:bg-[rgba(21,94,239,0.06)]'
|
||||
@@ -580,7 +580,7 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
</>
|
||||
);
|
||||
|
||||
// Tabs 配置
|
||||
// Tabs configuration
|
||||
const tabItems = [
|
||||
{
|
||||
key: 'basic',
|
||||
@@ -607,16 +607,16 @@ const CreateModal = forwardRef<CreateModalRef, CreateModalRefProps>(({
|
||||
form={form}
|
||||
layout="vertical"
|
||||
initialValues={{
|
||||
permission_id: 'Private', // 设置 permission_id 的默认值
|
||||
permission_id: 'Private', // Set default value for permission_id
|
||||
type: currentType,
|
||||
parser_config: {
|
||||
graphrag: {
|
||||
use_graphrag: false, // 默认不启用知识图谱
|
||||
scene_name: '', // 场景名称
|
||||
entity_types: '' as any, // 实体类型(界面上显示为字符串,保存时转为数组)
|
||||
method: 'general', // 默认使用通用方法
|
||||
resolution: false, // 默认不启用实体归一化
|
||||
community: false, // 默认不生成社区报告
|
||||
use_graphrag: false, // Default not to enable knowledge graph
|
||||
scene_name: '', // Scene name
|
||||
entity_types: '' as any, // Entity types (displayed as string in UI, converted to array when saving)
|
||||
method: 'general', // Default to use general method
|
||||
resolution: false, // Default not to enable entity normalization
|
||||
community: false, // Default not to generate community reports
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -17,13 +17,13 @@ const DelimiterSelector: FC<DelimiterSelectorProps> = ({
|
||||
className = '',
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
// 默认值为空字符串(不设置)
|
||||
// Default value is empty string (not set)
|
||||
const [selectedValue, setSelectedValue] = useState<string>(value || '');
|
||||
const [customValue, setCustomValue] = useState<string>('');
|
||||
const [showCustomInput, setShowCustomInput] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
// 检查当前值是否为自定义值
|
||||
// Check if current value is a custom delimiter
|
||||
if (value && isCustomDelimiter(value) && value !== 'custom') {
|
||||
setSelectedValue('custom');
|
||||
setCustomValue(value);
|
||||
@@ -39,15 +39,15 @@ const DelimiterSelector: FC<DelimiterSelectorProps> = ({
|
||||
|
||||
if (val === 'custom') {
|
||||
setShowCustomInput(true);
|
||||
// 如果已有自定义值,使用它;否则等待用户输入
|
||||
// If custom value exists, use it; otherwise wait for user input
|
||||
if (customValue) {
|
||||
onChange?.(customValue);
|
||||
} else {
|
||||
// 自定义但还没输入值,暂不触发 onChange
|
||||
// Custom selected but no value entered yet, don't trigger onChange
|
||||
onChange?.(undefined);
|
||||
}
|
||||
} else if (val === '') {
|
||||
// 选择"不设置"时,返回 undefined(不传递该参数)
|
||||
// When "Not set" is selected, return undefined (don't pass this parameter)
|
||||
setShowCustomInput(false);
|
||||
onChange?.(undefined);
|
||||
} else {
|
||||
@@ -59,7 +59,7 @@ const DelimiterSelector: FC<DelimiterSelectorProps> = ({
|
||||
const handleCustomInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const val = e.target.value;
|
||||
setCustomValue(val);
|
||||
// 只有当输入不为空时才触发 onChange
|
||||
// Only trigger onChange when input is not empty
|
||||
onChange?.(val || undefined);
|
||||
};
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ interface FolderTreeProps {
|
||||
onRootLoad?: (nodes: TreeNodeData[] | null) => void;
|
||||
onFolderPathChange?: (path: Array<{ id: string; name: string }>) => void;
|
||||
selectedKeys?: React.Key[];
|
||||
// 新增:自动展开到指定路径
|
||||
// New: Auto expand to specified path
|
||||
autoExpandPath?: Array<{ id: string; name: string }>;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ const extractItems = (resp: any): any[] => {
|
||||
return [];
|
||||
};
|
||||
|
||||
// 只加载当前层级的节点,不递归加载子节点
|
||||
// Only load nodes at current level, don't recursively load child nodes
|
||||
const buildTreeNodes = async (
|
||||
kbId: string,
|
||||
parentId: string,
|
||||
@@ -229,7 +229,7 @@ const buildTreeNodes = async (
|
||||
const currentParent = String(parentId ?? '');
|
||||
if (!currentParent) return [];
|
||||
|
||||
// 只请求一次当前层级的数据,不分页
|
||||
// Only request current level data once, no pagination
|
||||
const response = await getFolderList({
|
||||
kb_id: kbId,
|
||||
parent_id: currentParent,
|
||||
@@ -246,20 +246,20 @@ const buildTreeNodes = async (
|
||||
const nodeKey = String(keySource);
|
||||
const isFolder = isFolderLike(raw);
|
||||
|
||||
// 只显示文件夹
|
||||
// Only show folders
|
||||
if (!isFolder) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 文件夹节点初始不加载子节点,isLeaf设为false表示可能有子节点
|
||||
// Folder node initially doesn't load child nodes, isLeaf set to false indicates possible child nodes
|
||||
nodes.push({
|
||||
key: nodeKey,
|
||||
title: getNodeTitle(raw),
|
||||
icon: getNodeIcon(raw, isFolder),
|
||||
switcherIcon: isFolder ? switcherIcon : undefined,
|
||||
type: isFolder ? 'folder' : (typeof raw?.type === 'string' ? raw.type : normalizeExt(raw?.file_ext) || 'file'),
|
||||
isLeaf: false, // 文件夹节点初始设为false,表示可能有子节点,需要展开时加载
|
||||
children: undefined, // 初始不加载子节点
|
||||
isLeaf: false, // Folder node initially set to false, indicating possible child nodes, load when expanded
|
||||
children: undefined, // Initially don't load child nodes
|
||||
});
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
|
||||
const [autoExpandInProgress, setAutoExpandInProgress] = useState(false);
|
||||
|
||||
// 更新树节点数据的辅助函数
|
||||
// Helper function to update tree node data
|
||||
const updateTreeData = (nodes: TreeNodeData[], key: Key, children: TreeNodeData[]): TreeNodeData[] => {
|
||||
return nodes.map((node) => {
|
||||
if (node.key === key) {
|
||||
@@ -303,17 +303,17 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
});
|
||||
};
|
||||
|
||||
// 加载根节点
|
||||
// Load root nodes
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const load = async () => {
|
||||
if (!knowledgeBaseId) {
|
||||
setTreeData([]);
|
||||
setExpandedKeys([]); // 重置展开状态
|
||||
setExpandedKeys([]); // Reset expand state
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 重置展开状态,确保从根目录开始
|
||||
// Reset expand state, ensure starting from root directory
|
||||
setExpandedKeys([]);
|
||||
|
||||
const nodes = await buildTreeNodes(knowledgeBaseId, knowledgeBaseId);
|
||||
@@ -324,7 +324,7 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载文件夹树失败:', e);
|
||||
console.error('Failed to load folder tree:', e);
|
||||
if (!cancelled) {
|
||||
const fallback = buildMockTreeData();
|
||||
setTreeData(fallback);
|
||||
@@ -340,27 +340,27 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
};
|
||||
}, [knowledgeBaseId, refreshKey]);
|
||||
|
||||
// 懒加载子节点 - 只在展开时加载
|
||||
// Lazy load child nodes - only load when expanded
|
||||
const onLoadData = async (node: any) => {
|
||||
const { key } = node;
|
||||
|
||||
// 如果已经加载过子节点,不再重复加载
|
||||
// If child nodes already loaded, don't reload
|
||||
if (node.children !== undefined) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
try {
|
||||
// 使用节点的 key 作为 parent_id 加载子文件夹
|
||||
// Use node's key as parent_id to load child folders
|
||||
const children = await buildTreeNodes(knowledgeBaseId, String(key));
|
||||
setTreeData((prevData) => updateTreeData(prevData, key, children));
|
||||
} catch (e) {
|
||||
console.error('加载子节点失败:', e);
|
||||
// 加载失败时,将该节点标记为叶子节点(没有子节点)
|
||||
console.error('Failed to load child nodes:', e);
|
||||
// On load failure, mark this node as leaf node (no child nodes)
|
||||
setTreeData((prevData) => updateTreeData(prevData, key, []));
|
||||
}
|
||||
};
|
||||
|
||||
// 查找节点路径的辅助函数
|
||||
// Helper function to find node path
|
||||
const findNodePath = (nodes: TreeNodeData[], targetKey: Key, currentPath: Array<{ id: string; name: string }> = []): Array<{ id: string; name: string }> | null => {
|
||||
for (const node of nodes) {
|
||||
const newPath = [...currentPath, { id: String(node.key), name: String(node.title) }];
|
||||
@@ -379,7 +379,7 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
// 查找节点的辅助函数
|
||||
// Helper function to find node
|
||||
const findNodeInTree = (nodes: TreeNodeData[], key: string): TreeNodeData | null => {
|
||||
for (const node of nodes) {
|
||||
if (String(node.key) === key) {
|
||||
@@ -393,7 +393,7 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
// 渐进式自动展开到指定路径
|
||||
// Progressive auto expand to specified path
|
||||
useEffect(() => {
|
||||
if (!autoExpandPath || autoExpandPath.length === 0 || autoExpandInProgress || treeData.length === 0) {
|
||||
return;
|
||||
@@ -406,46 +406,46 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
const keysToExpand: React.Key[] = [];
|
||||
let currentTreeData = treeData;
|
||||
|
||||
// 逐级展开,从第一级开始(跳过根节点,因为根节点已经加载)
|
||||
// Expand level by level, starting from first level (skip root node as it's already loaded)
|
||||
for (let i = 0; i < autoExpandPath.length - 1; i++) {
|
||||
const nodeKey = autoExpandPath[i].id;
|
||||
keysToExpand.push(nodeKey);
|
||||
|
||||
// 查找当前节点
|
||||
// Find current node
|
||||
const targetNode = findNodeInTree(currentTreeData, nodeKey);
|
||||
|
||||
if (targetNode && targetNode.children === undefined) {
|
||||
// 如果子节点未加载,先加载
|
||||
// If child nodes not loaded, load first
|
||||
try {
|
||||
console.log(`自动展开:加载节点 ${nodeKey} 的子节点`);
|
||||
console.log(`Auto expand: Loading child nodes of ${nodeKey}`);
|
||||
const children = await buildTreeNodes(knowledgeBaseId, nodeKey);
|
||||
|
||||
// 更新树数据
|
||||
// Update tree data
|
||||
setTreeData((prevData) => {
|
||||
const newData = updateTreeData(prevData, nodeKey, children);
|
||||
currentTreeData = newData; // 更新当前引用
|
||||
currentTreeData = newData; // Update current reference
|
||||
return newData;
|
||||
});
|
||||
|
||||
// 等待状态更新完成
|
||||
// Wait for state update to complete
|
||||
await new Promise(resolve => setTimeout(resolve, 150));
|
||||
|
||||
} catch (error) {
|
||||
console.error(`自动展开时加载节点 ${nodeKey} 失败:`, error);
|
||||
// 加载失败时停止展开
|
||||
console.error(`Failed to load node ${nodeKey} during auto expand:`, error);
|
||||
// Stop expanding on load failure
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置展开的节点
|
||||
// Set expanded nodes
|
||||
setExpandedKeys(keysToExpand);
|
||||
|
||||
// 选中最后一个节点(目标文件夹)
|
||||
// Select last node (target folder)
|
||||
const targetKey = autoExpandPath[autoExpandPath.length - 1]?.id;
|
||||
if (targetKey) {
|
||||
console.log(`自动展开:选中目标节点 ${targetKey}`);
|
||||
// 延迟选中,确保展开动画完成
|
||||
console.log(`Auto expand: Select target node ${targetKey}`);
|
||||
// Delay selection to ensure expand animation completes
|
||||
setTimeout(() => {
|
||||
if (onSelect) {
|
||||
onSelect([targetKey], {
|
||||
@@ -460,21 +460,21 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('自动展开路径失败:', error);
|
||||
console.error('Auto expand path failed:', error);
|
||||
} finally {
|
||||
// 延迟重置标志,确保展开过程完全完成
|
||||
// Delay reset flag to ensure expand process is fully complete
|
||||
setTimeout(() => {
|
||||
setAutoExpandInProgress(false);
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
|
||||
// 延迟执行,确保树数据已经加载完成
|
||||
// Delay execution to ensure tree data is loaded
|
||||
const timer = setTimeout(expandToPath, 300);
|
||||
return () => clearTimeout(timer);
|
||||
}, [autoExpandPath, treeData.length, knowledgeBaseId, onSelect, autoExpandInProgress]);
|
||||
|
||||
// 处理展开事件
|
||||
// Handle expand event
|
||||
const handleExpand: TreeProps['onExpand'] = (expandedKeys, info) => {
|
||||
setExpandedKeys(expandedKeys);
|
||||
if (onExpand) {
|
||||
@@ -482,7 +482,7 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
// 处理选择事件,计算并传递路径
|
||||
// Handle select event, calculate and pass path
|
||||
const handleSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
|
||||
if (selectedKeys.length > 0) {
|
||||
const path = findNodePath(treeData, selectedKeys[0]);
|
||||
@@ -493,7 +493,7 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
onFolderPathChange([]);
|
||||
}
|
||||
|
||||
// 调用原始的 onSelect 回调
|
||||
// Call original onSelect callback
|
||||
if (onSelect) {
|
||||
onSelect(selectedKeys, info);
|
||||
}
|
||||
@@ -503,7 +503,7 @@ const FolderTree: FC<FolderTreeProps> = ({
|
||||
|
||||
return (
|
||||
<DirectoryTree
|
||||
key={refreshKey} // 添加key确保refreshKey变化时重新渲染整个组件
|
||||
key={refreshKey} // Add key to ensure component re-renders when refreshKey changes
|
||||
multiple={multiple}
|
||||
className={className}
|
||||
style={style}
|
||||
|
||||
@@ -130,7 +130,7 @@ const InsertModal = forwardRef<InsertModalRef, InsertModalProps>(({ onInsert, on
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('操作失败:', error);
|
||||
console.error('Operation failed:', error);
|
||||
const errorMsg = isEditMode
|
||||
? (t('knowledgeBase.updateFailed') || '更新失败')
|
||||
: (t('knowledgeBase.insertFailed') || '插入失败');
|
||||
|
||||
@@ -9,7 +9,7 @@ import pointer from '@/assets/images/userMemory/pointer.svg'
|
||||
import empty from '@/assets/images/userMemory/empty.svg'
|
||||
import Empty from '@/components/Empty'
|
||||
|
||||
// 知识图谱数据类型定义
|
||||
// Knowledge graph data type definitions
|
||||
export interface KnowledgeNode {
|
||||
id: string
|
||||
entity_name: string
|
||||
@@ -17,7 +17,7 @@ export interface KnowledgeNode {
|
||||
description: string
|
||||
pagerank: number
|
||||
source_id: string[]
|
||||
// ECharts 需要的属性
|
||||
// Properties required by ECharts
|
||||
name: string
|
||||
category: number
|
||||
symbolSize: number
|
||||
@@ -35,7 +35,7 @@ export interface KnowledgeEdge {
|
||||
source_id: string[]
|
||||
source: string
|
||||
target: string
|
||||
// ECharts 需要的属性
|
||||
// Properties required by ECharts
|
||||
value: number
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ const operations = [
|
||||
{ name: 'zoom', icon: zoom },
|
||||
]
|
||||
|
||||
// 预定义的颜色调色板
|
||||
// Predefined color palette
|
||||
const colorPalette = [
|
||||
'#155EEF', '#4DA8FF', '#9C6FFF', '#8BAEF7', '#369F21',
|
||||
'#FF5D34', '#FF8A4C', '#FFB048', '#E74C3C', '#9B59B6',
|
||||
@@ -73,7 +73,7 @@ const colorPalette = [
|
||||
'#8E44AD', '#2980B9', '#16A085', '#F1C40F', '#E67E22'
|
||||
]
|
||||
|
||||
// 动态生成实体类型颜色映射
|
||||
// Dynamically generate entity type color mapping
|
||||
const generateEntityTypeColors = (entityTypes: string[]): Record<string, string> => {
|
||||
const colorMap: Record<string, string> = {}
|
||||
entityTypes.forEach((type, index) => {
|
||||
@@ -93,12 +93,12 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
const [selectedNode, setSelectedNode] = useState<KnowledgeNode | null>(null)
|
||||
const [entityTypeColors, setEntityTypeColors] = useState<Record<string, string>>({})
|
||||
|
||||
// 弹框拖动相关状态
|
||||
// Modal drag-related state
|
||||
const [modalPosition, setModalPosition] = useState({ x: 20, y: 20 })
|
||||
const [isDragging, setIsDragging] = useState(false)
|
||||
const [dragStart, setDragStart] = useState({ x: 0, y: 0 })
|
||||
|
||||
// 拖动处理函数
|
||||
// Drag handling functions
|
||||
const handleMouseDown = useCallback((e: React.MouseEvent) => {
|
||||
setIsDragging(true)
|
||||
setDragStart({
|
||||
@@ -113,7 +113,7 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
const newX = e.clientX - dragStart.x
|
||||
const newY = e.clientY - dragStart.y
|
||||
|
||||
// 限制拖动范围,确保弹框不会超出容器
|
||||
// Limit drag range to ensure modal doesn't exceed container bounds
|
||||
const container = chartRef.current?.getEchartsInstance().getDom().parentElement
|
||||
if (container && modalRef.current) {
|
||||
const containerRect = container.getBoundingClientRect()
|
||||
@@ -133,7 +133,7 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
setIsDragging(false)
|
||||
}, [])
|
||||
|
||||
// 添加全局鼠标事件监听
|
||||
// Add global mouse event listeners
|
||||
useEffect(() => {
|
||||
if (isDragging) {
|
||||
document.addEventListener('mousemove', handleMouseMove)
|
||||
@@ -145,12 +145,12 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
}
|
||||
}, [isDragging, handleMouseMove, handleMouseUp])
|
||||
|
||||
// 关闭弹框
|
||||
// Close modal
|
||||
const handleCloseModal = useCallback(() => {
|
||||
setSelectedNode(null)
|
||||
}, [])
|
||||
|
||||
// 处理知识图谱数据
|
||||
// Process knowledge graph data
|
||||
const processGraphData = useCallback(() => {
|
||||
if (!data?.graph) {
|
||||
setNodes([])
|
||||
@@ -164,31 +164,31 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
const processedNodes: KnowledgeNode[] = []
|
||||
const processedEdges: KnowledgeEdge[] = []
|
||||
|
||||
// 获取所有实体类型
|
||||
// Get all entity types
|
||||
const entityTypes = [...new Set(rawNodes.map(node => node.entity_type))]
|
||||
const categoryMap = entityTypes.reduce((acc, type, index) => {
|
||||
acc[type] = index
|
||||
return acc
|
||||
}, {} as Record<string, number>)
|
||||
|
||||
// 动态生成实体类型颜色映射
|
||||
// Dynamically generate entity type color mapping
|
||||
const dynamicEntityTypeColors = generateEntityTypeColors(entityTypes)
|
||||
setEntityTypeColors(dynamicEntityTypeColors)
|
||||
|
||||
// 计算每个节点的连接数
|
||||
// Calculate connection count for each node
|
||||
const connectionCount: Record<string, number> = {}
|
||||
rawEdges.forEach(edge => {
|
||||
// 使用 src_id 和 tgt_id 计算连接数
|
||||
// Use src_id and tgt_id to calculate connection count
|
||||
connectionCount[edge.src_id] = (connectionCount[edge.src_id] || 0) + 1
|
||||
connectionCount[edge.tgt_id] = (connectionCount[edge.tgt_id] || 0) + 1
|
||||
})
|
||||
|
||||
// 处理节点数据
|
||||
// Process node data
|
||||
rawNodes.forEach(node => {
|
||||
const connections = connectionCount[node.id] || 0
|
||||
const categoryIndex = categoryMap[node.entity_type] || 0
|
||||
|
||||
// 根据 pagerank 和连接数计算节点大小
|
||||
// Calculate node size based on pagerank and connection count
|
||||
let symbolSize = Math.max(10, Math.min(50, node.pagerank * 200 + connections * 2))
|
||||
|
||||
processedNodes.push({
|
||||
@@ -202,19 +202,19 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
})
|
||||
})
|
||||
|
||||
// 处理边数据
|
||||
// Process edge data
|
||||
rawEdges.forEach(edge => {
|
||||
// 注意:根据数据结构,source 和 target 字段可能与 src_id 和 tgt_id 相反
|
||||
// 我们使用 src_id 和 tgt_id 作为正确的连接关系
|
||||
// Note: Based on data structure, source and target fields may be opposite to src_id and tgt_id
|
||||
// We use src_id and tgt_id as the correct connection relationship
|
||||
processedEdges.push({
|
||||
...edge, // 保留所有原始字段
|
||||
source: edge.src_id, // 使用 src_id 作为源节点
|
||||
target: edge.tgt_id, // 使用 tgt_id 作为目标节点
|
||||
...edge, // Keep all original fields
|
||||
source: edge.src_id, // Use src_id as source node
|
||||
target: edge.tgt_id, // Use tgt_id as target node
|
||||
value: edge.weight || 1
|
||||
})
|
||||
})
|
||||
|
||||
// 验证节点ID和边的连接
|
||||
// Verify node IDs and edge connections
|
||||
const nodeIds = new Set(processedNodes.map(n => n.id))
|
||||
const validEdges = processedEdges.filter(edge => {
|
||||
const sourceExists = nodeIds.has(edge.source)
|
||||
@@ -225,18 +225,18 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
return sourceExists && targetExists
|
||||
})
|
||||
|
||||
// 调试信息
|
||||
// Debug information
|
||||
console.log('Total nodes:', processedNodes.length)
|
||||
console.log('Total edges:', processedEdges.length)
|
||||
console.log('Valid edges:', validEdges.length)
|
||||
console.log('Node IDs:', Array.from(nodeIds).slice(0, 5))
|
||||
console.log('Edge sample:', validEdges.slice(0, 3))
|
||||
|
||||
// 设置分类
|
||||
// Set categories
|
||||
const processedCategories = entityTypes.map(type => ({ name: type }))
|
||||
|
||||
setNodes(processedNodes)
|
||||
setLinks(validEdges) // 只使用有效的边
|
||||
setLinks(validEdges) // Only use valid edges
|
||||
setCategories(processedCategories)
|
||||
}, [data])
|
||||
|
||||
@@ -334,7 +334,7 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
lineStyle: {
|
||||
color: '#5B6167',
|
||||
curveness: 0.3,
|
||||
width: 2, // 固定线宽,避免函数问题
|
||||
width: 2, // Fixed line width to avoid function issues
|
||||
opacity: 0.8
|
||||
},
|
||||
force: {
|
||||
@@ -376,7 +376,7 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 实体详情弹框 */}
|
||||
{/* Entity details modal */}
|
||||
{selectedNode && (
|
||||
<div
|
||||
ref={modalRef}
|
||||
@@ -387,7 +387,7 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
cursor: isDragging ? 'grabbing' : 'grab'
|
||||
}}
|
||||
>
|
||||
{/* 弹框头部 - 可拖动区域 */}
|
||||
{/* Modal header - draggable area */}
|
||||
<div
|
||||
className="rb:flex rb:items-center rb:justify-between rb:mb-3 rb:pb-2 rb:border-b rb:border-[#EBEBEB] rb:cursor-grab"
|
||||
onMouseDown={handleMouseDown}
|
||||
@@ -404,7 +404,7 @@ const KnowledgeGraph: FC<KnowledgeGraphProps> = ({ data, loading = false }) => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 弹框内容 */}
|
||||
{/* Modal content */}
|
||||
<div>
|
||||
<div className="rb:font-medium rb:mb-4">
|
||||
<div className="rb:text-[16px] rb:mb-2">{selectedNode.entity_name}</div>
|
||||
|
||||
@@ -15,7 +15,7 @@ import { type KnowledgeBase } from '../types';
|
||||
import Empty from '@/components/Empty';
|
||||
interface KnowledgeGraphCardProps {
|
||||
knowledgeBase?: KnowledgeBase;
|
||||
onRebuildGraph?: () => void; // 添加重建图谱的回调函数
|
||||
onRebuildGraph?: () => void; // Callback function to rebuild graph
|
||||
}
|
||||
|
||||
const KnowledgeGraphCard: React.FC<KnowledgeGraphCardProps> = ({ knowledgeBase, onRebuildGraph }) => {
|
||||
@@ -23,7 +23,7 @@ const KnowledgeGraphCard: React.FC<KnowledgeGraphCardProps> = ({ knowledgeBase,
|
||||
const [data, setData] = useState<KnowledgeGraphResponse | undefined>()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const handleRebuildGraph = () => {
|
||||
// 调用父组件传递的回调函数来打开CreateModal并传递重建标识
|
||||
// Call parent component's callback to open CreateModal with rebuild flag
|
||||
if (onRebuildGraph) {
|
||||
onRebuildGraph();
|
||||
}
|
||||
@@ -38,15 +38,15 @@ const KnowledgeGraphCard: React.FC<KnowledgeGraphCardProps> = ({ knowledgeBase,
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await getKnowledgeGraph(knowledgeBase?.id)
|
||||
// 判断 res.graph 是否为空对象或不存在
|
||||
// Check if res.graph is empty object or doesn't exist
|
||||
const graphResponse = res as KnowledgeGraphResponse;
|
||||
if (!graphResponse || !graphResponse.graph || Object.keys(graphResponse.graph).length === 0) {
|
||||
setData(undefined) // 设置为 undefined 以显示 empty 状态
|
||||
setData(undefined) // Set to undefined to show empty state
|
||||
} else {
|
||||
setData(graphResponse)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取知识图谱数据失败:', error)
|
||||
console.error('Failed to fetch knowledge graph data:', error)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
{ label: t('knowledgeBase.vector'), value: false },
|
||||
]);
|
||||
|
||||
// 获取检索模式选项
|
||||
// Get retrieval mode options
|
||||
useEffect(() => {
|
||||
fetchRetrievalModeOptions();
|
||||
}, []);
|
||||
@@ -36,9 +36,9 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
try {
|
||||
const response = await getRetrievalModeType();
|
||||
if (response && Array.isArray(response)) {
|
||||
// 将 API 返回的数据转换为选项格式
|
||||
// Convert API response to option format
|
||||
const options = response.map((item: any) => {
|
||||
// 支持多种数据格式
|
||||
// Support multiple data formats
|
||||
let label = t(`knowledgeBase.${item}`) + ' ' + t(`knowledgeBase.retrieve`);
|
||||
let value = item;
|
||||
|
||||
@@ -50,8 +50,8 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取检索模式选项失败:', error);
|
||||
// 保持默认选项
|
||||
console.error('Failed to fetch retrieval mode options:', error);
|
||||
// Keep default options
|
||||
}
|
||||
};
|
||||
|
||||
@@ -60,8 +60,8 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
setKnowledgeBaseId(kbId || '');
|
||||
form.resetFields();
|
||||
setData([]);
|
||||
setRetrieveType('hybrid'); // 重置为默认值
|
||||
// 确保表单字段也设置为默认值
|
||||
setRetrieveType('hybrid'); // Reset to default value
|
||||
// Ensure form field is also set to default value
|
||||
form.setFieldsValue({ retrieve_type: 'hybrid' });
|
||||
}
|
||||
const fetchData = (params: RecallTestParams) => {
|
||||
@@ -91,10 +91,10 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
console.log('RecallTest - params:', params);
|
||||
fetchData(params);
|
||||
}).catch((error) => {
|
||||
console.error('表单验证失败:', error);
|
||||
console.error('Form validation failed:', error);
|
||||
});
|
||||
}
|
||||
// 暴露给父组件的方法
|
||||
// Expose methods to parent component
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
}));
|
||||
@@ -134,7 +134,7 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{/* 当 retrieve_type = semantic 或 hybrid 时显示 */}
|
||||
{/* Show when retrieve_type = semantic or hybrid */}
|
||||
{(retrieveType === 'semantic' || retrieveType === 'hybrid') && (
|
||||
<Form.Item name="similarity_threshold" label={t('knowledgeBase.similarityThreshold')}>
|
||||
<Select
|
||||
@@ -155,7 +155,7 @@ const RecallTest = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
{/* 当 retrieve_type = participle 或 hybrid 时显示 */}
|
||||
{/* Show when retrieve_type = participle or hybrid */}
|
||||
{(retrieveType === 'participle' || retrieveType === 'hybrid') && (
|
||||
<Form.Item name="vector_similarity_weight" label={t('knowledgeBase.semanticSimilarity')}>
|
||||
<Select
|
||||
|
||||
@@ -12,7 +12,7 @@ const RecallTestDrawer = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
const pendingKbIdRef = useRef<string | undefined>(undefined);
|
||||
const shouldCallHandleOpenRef = useRef(false);
|
||||
|
||||
// 调用 RecallTest 的 handleOpen 方法
|
||||
// Call RecallTest's handleOpen method
|
||||
const callRecallTestHandleOpen = useCallback(() => {
|
||||
if (recallTestRef.current && shouldCallHandleOpenRef.current) {
|
||||
recallTestRef.current.handleOpen(pendingKbIdRef.current);
|
||||
@@ -26,14 +26,14 @@ const RecallTestDrawer = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
setOpen(true);
|
||||
}
|
||||
|
||||
// 当 Drawer 打开时,尝试调用 handleOpen
|
||||
// When Drawer opens, try to call handleOpen
|
||||
useLayoutEffect(() => {
|
||||
if (open) {
|
||||
callRecallTestHandleOpen();
|
||||
}
|
||||
}, [open, callRecallTestHandleOpen]);
|
||||
|
||||
// 使用回调 ref 确保在组件挂载后立即调用
|
||||
// Use callback ref to ensure immediate call after component mount
|
||||
const setRecallTestRef = useCallback((node: any) => {
|
||||
recallTestRef.current = node;
|
||||
if (open && shouldCallHandleOpenRef.current) {
|
||||
@@ -41,7 +41,7 @@ const RecallTestDrawer = forwardRef<RecallTestDrawerRef>(({},ref) => {
|
||||
}
|
||||
}, [open, callRecallTestHandleOpen]);
|
||||
|
||||
// 暴露给父组件的方法
|
||||
// Expose methods to parent component
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
}));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @Description: 滚动列表
|
||||
/**
|
||||
* @Description: Scroll List
|
||||
* @Version: 0.0.1
|
||||
* @Author: yujiangping
|
||||
* @Date: 2025-11-18 16:19:58
|
||||
@@ -22,9 +22,9 @@ interface RecallTestResultProps {
|
||||
loadMore?: () => void;
|
||||
loading?: boolean;
|
||||
scrollableTarget?: string;
|
||||
editable?: boolean; // 是否可编辑
|
||||
onItemClick?: (item: RecallTestData, index: number) => void; // 点击项的回调
|
||||
parserMode?: number; // 解析模式,1 表示 QA 格式
|
||||
editable?: boolean; // Whether editable
|
||||
onItemClick?: (item: RecallTestData, index: number) => void; // Click item callback
|
||||
parserMode?: number; // Parser mode, 1 means QA format
|
||||
}
|
||||
|
||||
const RecallTestResult = ({
|
||||
@@ -40,7 +40,7 @@ const RecallTestResult = ({
|
||||
}: RecallTestResultProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// 解析 QA 格式内容
|
||||
// Parse QA format content
|
||||
const parseQAContent = (content: string) => {
|
||||
if (!content || parserMode !== 1) return null;
|
||||
|
||||
@@ -56,25 +56,25 @@ const RecallTestResult = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
// 格式化 QA 内容为显示格式
|
||||
// Format QA content for display
|
||||
const formatQAContent = (question: string, answer: string) => {
|
||||
return `**${t('knowledgeBase.question')}:** ${question}\n**${t('knowledgeBase.answer')}:** ${answer}`;
|
||||
};
|
||||
|
||||
const handleItemClick = (e: React.MouseEvent, item: RecallTestData, index: number) => {
|
||||
// 检查点击的是否是图片或图片相关元素
|
||||
// Check if the click is on an image or image-related element
|
||||
const target = e.target as HTMLElement;
|
||||
|
||||
// 检查是否点击了图片本身、图片的容器、预览层、关闭按钮或 SVG 图标
|
||||
// Check if clicked on image itself, image container, preview layer, close button or SVG icon
|
||||
if (
|
||||
target.tagName === 'IMG' ||
|
||||
target.tagName === 'SVG' || // SVG 图标
|
||||
target.tagName === 'PATH' || // SVG 路径
|
||||
target.tagName === 'SVG' || // SVG icon
|
||||
target.tagName === 'PATH' || // SVG path
|
||||
target.closest('.ant-image') ||
|
||||
target.closest('.ant-image-preview') ||
|
||||
target.closest('.ant-image-preview-wrap') ||
|
||||
target.closest('.ant-image-preview-operations') ||
|
||||
target.closest('.anticon') || // Ant Design 图标
|
||||
target.closest('.anticon') || // Ant Design icon
|
||||
target.classList.contains('ant-image-img') ||
|
||||
target.classList.contains('ant-image-mask') ||
|
||||
target.classList.contains('ant-image-preview-close') ||
|
||||
@@ -88,7 +88,7 @@ const RecallTestResult = ({
|
||||
}
|
||||
};
|
||||
|
||||
// 根据分数获取颜色类名
|
||||
// Get color class based on score
|
||||
const getScoreColorClass = (score: number): string => {
|
||||
const percentage = score * 100;
|
||||
if (percentage >= 90) {
|
||||
@@ -177,7 +177,7 @@ const RecallTestResult = ({
|
||||
</div>
|
||||
);
|
||||
|
||||
// 如果提供了 loadMore 和 hasMore,使用 InfiniteScroll
|
||||
// If loadMore and hasMore are provided, use InfiniteScroll
|
||||
if (loadMore && hasMore !== undefined) {
|
||||
return (
|
||||
<div className='rb:flex rb:h-full rb:flex-col'>
|
||||
@@ -200,7 +200,7 @@ const RecallTestResult = ({
|
||||
);
|
||||
}
|
||||
|
||||
// 否则使用普通渲染
|
||||
// Otherwise use normal rendering
|
||||
return (
|
||||
<div className='rb:flex rb:flex-col'>
|
||||
<div className='rb:flex rb:items-center rb:justify-start rb:gap-2'>
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
* @Author: yujiangping
|
||||
* @Date: 2025-11-10 18:52:55
|
||||
* @LastEditors: yujiangping
|
||||
* @LastEditTime: 2025-11-29 12:29:31
|
||||
* @LastEditTime: 2026-02-03 17:08:00
|
||||
*/
|
||||
import { forwardRef, useImperativeHandle, useState, useRef } from 'react';
|
||||
import { Switch } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { message } from 'antd';
|
||||
import type { ShareModalRef, ShareModalRefProps, KnowledgeBase} from '@/views/KnowledgeBase/types';
|
||||
import type { ShareModalRef, ShareModalRefProps, KnowledgeBase, SpaceItem} from '@/views/KnowledgeBase/types';
|
||||
import RbModal from '@/components/RbModal'
|
||||
// import betchControlIcon from '@/assets/images/knowledgeBase/betch-control.png';
|
||||
import kbIcon from '@/assets/images/knowledgeBase/knowledge-management.png';
|
||||
@@ -33,7 +33,7 @@ const ShareModal = forwardRef<ShareModalRef,ShareModalRefProps>(({ handleShare:
|
||||
const [knowledgeBase, setKnowledgeBase] = useState<KnowledgeBase | null>(null);
|
||||
const [spaceList, setSpaceList] = useState<SpaceItem[]>([]);
|
||||
|
||||
// 封装取消方法,添加关闭弹窗逻辑
|
||||
// Close modal and reset state
|
||||
const handleClose = () => {
|
||||
setCurIndex(9999);
|
||||
setLoading(false)
|
||||
@@ -66,11 +66,11 @@ const ShareModal = forwardRef<ShareModalRef,ShareModalRefProps>(({ handleShare:
|
||||
console.log('Workspace IDs:', workspaceIds);
|
||||
shareSpaceModalRef?.current?.handleOpen(kbId,knowledgeBase,workspaceIds);
|
||||
|
||||
// 分享后关闭弹窗
|
||||
// Close modal after sharing
|
||||
handleClose();
|
||||
}
|
||||
const handleChange = (checked: boolean, item: any) => {
|
||||
// 打开/关闭分享出去的数据库
|
||||
// Toggle shared knowledge base status
|
||||
console.log('Switch changed:', checked, item);
|
||||
updateKnowledgeBase(item.target_kb?.id, {
|
||||
status: checked ? 1 : 2
|
||||
@@ -82,7 +82,7 @@ const ShareModal = forwardRef<ShareModalRef,ShareModalRefProps>(({ handleShare:
|
||||
})
|
||||
}
|
||||
|
||||
// 暴露给父组件的方法
|
||||
// Expose methods to parent component
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
handleClose,
|
||||
|
||||
@@ -30,7 +30,7 @@ const ShareModal = forwardRef<ShareModalRef,ShareModalRefProps>(({ handleShare:
|
||||
const [knowledgeBase, setKnowledgeBase] = useState<KnowledgeBase | null>(null);
|
||||
const [spaceList, setSpaceList] = useState<SpaceItem[]>([]);
|
||||
|
||||
// 封装取消方法,添加关闭弹窗逻辑
|
||||
// Close modal and reset state
|
||||
const handleClose = () => {
|
||||
setCurIndex(-1);
|
||||
setLoading(false)
|
||||
@@ -51,10 +51,10 @@ const ShareModal = forwardRef<ShareModalRef,ShareModalRefProps>(({ handleShare:
|
||||
}
|
||||
const handleShare = async() => {
|
||||
|
||||
// 获取所有 checked 为 true 的数据
|
||||
// Get all data with checked = true
|
||||
const checkedItems = spaceList.filter(item => item.is_active);
|
||||
debugger
|
||||
// 获取当前选中的项(curIndex 对应的数据)
|
||||
// Get currently selected item (corresponding to curIndex)
|
||||
const selectedItem = curIndex !== -1 ? spaceList[curIndex] : null;
|
||||
if(!selectedItem){
|
||||
messageApi.error(t('knowledgeBase.selectSpace'));
|
||||
@@ -70,13 +70,13 @@ const ShareModal = forwardRef<ShareModalRef,ShareModalRefProps>(({ handleShare:
|
||||
}else{
|
||||
messageApi.error(t('knowledgeBase.shareFailed'));
|
||||
}
|
||||
// 调用父组件传递的回调函数,传递选中的数据
|
||||
// Call parent component's callback function with selected data
|
||||
onShare?.({
|
||||
checkedItems,
|
||||
selectedItem
|
||||
});
|
||||
|
||||
// 分享后关闭弹窗
|
||||
// Close modal after sharing
|
||||
handleClose();
|
||||
}
|
||||
const handleClick = (index: number, checked: boolean) => {
|
||||
@@ -84,7 +84,7 @@ const ShareModal = forwardRef<ShareModalRef,ShareModalRefProps>(({ handleShare:
|
||||
setCurIndex(index);
|
||||
}
|
||||
|
||||
// 暴露给父组件的方法
|
||||
// Expose methods to parent component
|
||||
useImperativeHandle(ref, () => ({
|
||||
handleOpen,
|
||||
handleClose,
|
||||
|
||||
Reference in New Issue
Block a user