From 28b8067c458e2687bf3401b08dcddbccb43ec0f8 Mon Sep 17 00:00:00 2001 From: lmr <350416710@qq.com> Date: Tue, 16 Sep 2025 22:17:42 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/KnowledgePage/KnowledgeFile.tsx | 4 +- .../src/pages/KnowledgePage/KnowledgeQa.tsx | 9 +- .../components/FileUploadStep2.tsx | 6 +- .../pages/KnowledgePage/components/Files.tsx | 183 +++++++----------- .../KnowledgePage/components/PreviewFile.tsx | 3 +- .../components/PreviewResult.tsx | 16 +- .../KnowledgePage/components/RuleFile.tsx | 2 +- 7 files changed, 99 insertions(+), 124 deletions(-) diff --git a/src/frontend/platform/src/pages/KnowledgePage/KnowledgeFile.tsx b/src/frontend/platform/src/pages/KnowledgePage/KnowledgeFile.tsx index 0919d4df6..02a36fab1 100644 --- a/src/frontend/platform/src/pages/KnowledgePage/KnowledgeFile.tsx +++ b/src/frontend/platform/src/pages/KnowledgePage/KnowledgeFile.tsx @@ -523,8 +523,8 @@ const handleCopy = async (elem) => { handleCachePage(); }} > -
-
+
+
diff --git a/src/frontend/platform/src/pages/KnowledgePage/KnowledgeQa.tsx b/src/frontend/platform/src/pages/KnowledgePage/KnowledgeQa.tsx index ba933bf6b..72638cdee 100644 --- a/src/frontend/platform/src/pages/KnowledgePage/KnowledgeQa.tsx +++ b/src/frontend/platform/src/pages/KnowledgePage/KnowledgeQa.tsx @@ -238,7 +238,7 @@ export default function KnowledgeQa(params) { {t('lib.createUser')} - + {t('operations')} @@ -255,8 +255,8 @@ export default function KnowledgeQa(params) { }} > {/* 名称+描述单元格:恢复原有气泡结构,确保蓝色生效 */} - -
+ +
知识库图标 - {el.update_time.replace('T', ' ')} + {el.update_time.replace('T', ' ')}
{el.user_name || '--'}
@@ -305,7 +305,6 @@ export default function KnowledgeQa(params) { diff --git a/src/frontend/platform/src/pages/KnowledgePage/components/FileUploadStep2.tsx b/src/frontend/platform/src/pages/KnowledgePage/components/FileUploadStep2.tsx index a4461c879..558ae90fe 100644 --- a/src/frontend/platform/src/pages/KnowledgePage/components/FileUploadStep2.tsx +++ b/src/frontend/platform/src/pages/KnowledgePage/components/FileUploadStep2.tsx @@ -175,8 +175,8 @@ useEffect(() => { displayStep === 2 && (
{ {t('defaultStrategy')} {t('customStrategy')} - ) :
} + ) :
}
{/* 文件文档设置 */} diff --git a/src/frontend/platform/src/pages/KnowledgePage/components/Files.tsx b/src/frontend/platform/src/pages/KnowledgePage/components/Files.tsx index 0bb7fd169..ccb95f3b2 100644 --- a/src/frontend/platform/src/pages/KnowledgePage/components/Files.tsx +++ b/src/frontend/platform/src/pages/KnowledgePage/components/Files.tsx @@ -39,15 +39,16 @@ export default function Files({ onPreview }) { ) const navigate = useNavigate() - // 新增状态 + // 存储完整文件对象(保留所有原始参数) + const [selectedFileObjs, setSelectedFileObjs] = useState>>([]); + const [isAllSelected, setIsAllSelected] = useState(false); + + // 其他原有状态 const [selectedFilters, setSelectedFilters] = useState([]); const [tempFilters, setTempFilters] = useState([]); const [isFilterOpen, setIsFilterOpen] = useState(false); - const [selectedFiles, setSelectedFiles] = useState>(new Set()); - // 新增状态:跟踪全选状态 - const [isAllSelected, setIsAllSelected] = useState(false); - // 解析中 轮巡 + // 解析中轮巡 const timerRef = useRef(null) useEffect(() => { if (datalist.some(el => el.status === 1)) { @@ -62,21 +63,14 @@ export default function Files({ onPreview }) { setSelectedFilters([...tempFilters]); const params: any = {}; if (tempFilters.length > 0) { - // 创建多个 status 参数 - tempFilters.forEach((status, index) => { - params[`status`] = status; // 这会覆盖前一个,需要特殊处理 - }); - - // 或者使用另一种方式:修改 useTable 支持数组 - params.status = tempFilters; // 传递数组,让 useTable 处理 + params.status = tempFilters; } else { - // 如果没有选中任何筛选条件,传递空对象来重置筛选 params.status = []; } filterData(params); setIsFilterOpen(false); - setSelectedFiles(new Set()); + setSelectedFileObjs([]); setIsAllSelected(false); }; @@ -86,8 +80,7 @@ export default function Files({ onPreview }) { setSelectedFilters(emptyFilters); filterData({ status: [] }); setIsFilterOpen(false); - // 重置筛选时清除选择状态 - setSelectedFiles(new Set()); + setSelectedFileObjs([]); setIsAllSelected(false); }; @@ -98,79 +91,67 @@ export default function Files({ onPreview }) { onOk(next) { captureAndAlertRequestErrorHoc(deleteFile(id).then(res => { reload() - // 删除文件后,从选中集合中移除 - setSelectedFiles(prev => { - const newSet = new Set(prev); - newSet.delete(id); - return newSet; - }); + setSelectedFileObjs(prev => prev.filter(file => file.id !== id)); })) next() }, }) } - // 重试解析 + // 重试解析(保留原始文件参数结构) const handleRetry = (files) => { captureAndAlertRequestErrorHoc(retryKnowledgeFileApi({ file_objs: files }).then(res => { reload() })) } - // 全选/取消全选 + // 全选/取消全选(存储完整文件对象) const toggleSelectAll = (checked: boolean) => { if (checked) { - // 全选当前页 - const currentPageIds = datalist.map(file => file.id); - const newSelectedFiles = new Set(selectedFiles); - currentPageIds.forEach(id => newSelectedFiles.add(id)); - setSelectedFiles(newSelectedFiles); - setIsAllSelected(true); + // 全选当前页并去重 + const newFiles = datalist + .filter(file => !selectedFileObjs.some(item => item.id === file.id)) + .map(file => ({ ...file })); // 深拷贝保留所有参数 + setSelectedFileObjs([...selectedFileObjs, ...newFiles]); } else { // 取消全选当前页 - const currentPageIds = datalist.map(file => file.id); - const newSelectedFiles = new Set(selectedFiles); - currentPageIds.forEach(id => newSelectedFiles.delete(id)); - setSelectedFiles(newSelectedFiles); - setIsAllSelected(false); + const currentPageIds = new Set(datalist.map(file => file.id)); + setSelectedFileObjs(prev => prev.filter(file => !currentPageIds.has(file.id))); } + setIsAllSelected(checked); }; // 单个文件选中/取消选中 - const toggleSelectFile = (fileId: string, checked: boolean) => { - const newSelectedFiles = new Set(selectedFiles); + const toggleSelectFile = (file: Record, checked: boolean) => { if (checked) { - newSelectedFiles.add(fileId); + // 避免重复添加 + if (!selectedFileObjs.some(item => item.id === file.id)) { + setSelectedFileObjs([...selectedFileObjs, { ...file }]); + } } else { - newSelectedFiles.delete(fileId); - // 如果有文件被取消选择,则取消全选状态 + setSelectedFileObjs(prev => prev.filter(item => item.id !== file.id)); setIsAllSelected(false); } - setSelectedFiles(newSelectedFiles); - }; - - // 获取选中的文件 - const getSelectedFiles = () => { - return datalist.filter(file => selectedFiles.has(file.id)); }; // 检查当前页是否全部选中 const isCurrentPageAllSelected = useMemo(() => { if (datalist.length === 0) return false; - return datalist.every(file => selectedFiles.has(file.id)); - }, [datalist, selectedFiles]); + const selectedIds = new Set(selectedFileObjs.map(file => file.id)); + return datalist.every(file => selectedIds.has(file.id)); + }, [datalist, selectedFileObjs]); // 批量删除 const handleBatchDelete = () => { bsConfirm({ title: t('prompt'), - desc: t('确认删除选中文件', { count: selectedFiles.size }), + desc: t('确认删除选中文件', { count: selectedFileObjs.length }), onOk(next) { captureAndAlertRequestErrorHoc(Promise.all( - Array.from(selectedFiles).map(id => deleteFile(id)) + selectedFileObjs.map(file => deleteFile(file.id)) ).then(() => { reload(); - setSelectedFiles(new Set()); + setSelectedFileObjs([]); setIsAllSelected(false); })) next(); @@ -178,17 +159,19 @@ export default function Files({ onPreview }) { }) } - // 批量重试 + // 批量重试(核心修复:传递完整文件对象) const handleBatchRetry = () => { - const failedFiles = getSelectedFiles().filter(file => file.status === 3); + // 筛选失败文件,保留完整参数 + const failedFiles = selectedFileObjs.filter(file => file.status === 3); + if (failedFiles.length > 0) { - handleRetry(failedFiles); - setSelectedFiles(new Set()); + handleRetry(failedFiles); // 直接传递完整文件对象数组 + setSelectedFileObjs([]); setIsAllSelected(false); } } - // 策略解析 + // 策略解析(原有逻辑不变) const dataSouce = useMemo(() => { return datalist.map(el => { if (!el.split_rule) return { @@ -206,32 +189,34 @@ export default function Files({ onPreview }) { }, [datalist]) const splitRuleDesc = (el) => { - if (!el.split_rule) return el.strategy[1].replace(/\n/g, '\\n') // 兼容历史数据 + if (!el.split_rule) return el.strategy[1].replace(/\n/g, '\\n') const suffix = el.file_name.split('.').pop().toUpperCase() const excel_rule = JSON.parse(el.split_rule).excel_rule - if (!excel_rule) return el.strategy[1].replace(/\n/g, '\\n') // 兼容历史数据 + if (!excel_rule) return el.strategy[1].replace(/\n/g, '\\n') return ['XLSX', 'XLS', 'CSV'].includes(suffix) ? `每 ${excel_rule.slice_length} 行作为一个分段` : el.strategy[1].replace(/\n/g, '\\n') } // 检查是否有选中的解析失败文件 const hasSelectedFailedFiles = useMemo(() => { - return getSelectedFiles().some(file => file.status === 3); - }, [selectedFiles, datalist]); + return selectedFileObjs.some(file => file.status === 3); + }, [selectedFileObjs]); + useEffect(() => { if (isFilterOpen) { setTempFilters([...selectedFilters]); } }, [isFilterOpen, selectedFilters]); - // 当页面数据变化时,更新全选状态 + // 页面数据变化时更新全选状态 useEffect(() => { - setIsAllSelected(datalist.length > 0 && datalist.every(file => selectedFiles.has(file.id))); - }, [datalist, selectedFiles]); + setIsAllSelected(datalist.length > 0 && datalist.every(file => + selectedFileObjs.some(item => item.id === file.id) + )); + }, [datalist, selectedFileObjs]); // 处理下拉菜单关闭事件 const handleOpenChange = (open: boolean) => { if (!open && isFilterOpen) { - // 当下拉菜单关闭且之前是打开状态时,应用筛选 applyFilters(); } setIsFilterOpen(open); @@ -246,32 +231,29 @@ export default function Files({ onPreview }) { )} {/* 顶部操作栏 */} - {selectedFiles.size > 0 && ( + {selectedFileObjs.length > 0 && (
- {/* 批量操作按钮组 */} - {selectedFiles.size > 0 && ( -
+
+ + {hasSelectedFailedFiles && ( - {hasSelectedFailedFiles && ( - - )} -
- )} + )} +
)} @@ -279,8 +261,7 @@ export default function Files({ onPreview }) {
{ search(e.target.value); - // 搜索时清除选择状态 - setSelectedFiles(new Set()); + setSelectedFileObjs([]); setIsAllSelected(false); }} /> {isEditable && ( @@ -329,7 +310,6 @@ export default function Files({ onPreview }) { value: 2, label: '已完成', color: 'text-green-500', - // 绿色圆点+文字(与表格"已完成"样式统一) icon: (
@@ -343,7 +323,6 @@ export default function Files({ onPreview }) { value: 1, label: '解析中', color: 'text-[#4D9BF0]', - // 蓝色圆点+文字(与表格"解析中"样式统一) icon: (
@@ -357,7 +336,6 @@ export default function Files({ onPreview }) { value: 3, label: '解析失败', color: 'text-red-500', - // 红色圆点+文字(与表格"解析失败"样式统一) icon: (
@@ -371,7 +349,6 @@ export default function Files({ onPreview }) { value: 4, label: '向量模型切换中', color: 'text-[#4D9BF0]', - // 蓝色圆点+文字(与表格"解析中"样式统一) icon: (
@@ -441,17 +418,17 @@ export default function Files({ onPreview }) { { - if (!selectedFiles.size && el.status !== 3 && el.status !== 1) { + if (selectedFileObjs.length === 0 && el.status !== 3 && el.status !== 1) { onPreview(el.id); } }} - className={selectedFiles.has(el.id) ? 'bg-blue-50' : ''} + className={selectedFileObjs.some(file => file.id === el.id) ? 'bg-blue-50' : ''} > file.id === el.id)} onCheckedChange={(checked) => { - toggleSelectFile(el.id, checked as boolean); + toggleSelectFile(el, checked as boolean); }} onClick={(e) => e.stopPropagation()} /> @@ -480,23 +457,20 @@ export default function Files({ onPreview }) { {el.update_time.replace('T', ' ')} + {console.log(el.remark,44444)} {el.status === 3 ? ( +
- - {/* 红色圆点 - 12x12px */} - - {/* 解析失败文字 - 符合Poppins SemiBold 14px样式 */} 解析失败 - - +
{el.remark}
@@ -507,10 +481,7 @@ export default function Files({ onPreview }) { {el.status === 2 ? ( - {/* 红色圆点 - 12x12px */} - - {/* 解析失败文字 - 符合Poppins SemiBold 14px样式 */} 已完成 @@ -519,10 +490,7 @@ export default function Files({ onPreview }) { ) : el.status === 1 ? ( - {/* 红色圆点 - 12x12px */} - - {/* 解析失败文字 - 符合Poppins SemiBold 14px样式 */} 解析中 @@ -531,10 +499,7 @@ export default function Files({ onPreview }) { ) : ( - {/* 红色圆点 - 12x12px */} - - {/* 解析失败文字 - 符合Poppins SemiBold 14px样式 */} 向量模型切换中 @@ -552,7 +517,7 @@ export default function Files({ onPreview }) { size="icon" onClick={(e) => { e.stopPropagation(); - handleRetry([el]); + handleRetry([el]); // 单个重试传递完整对象 }} title={t('重试')} > diff --git a/src/frontend/platform/src/pages/KnowledgePage/components/PreviewFile.tsx b/src/frontend/platform/src/pages/KnowledgePage/components/PreviewFile.tsx index d8ae5c65d..c146405d4 100644 --- a/src/frontend/platform/src/pages/KnowledgePage/components/PreviewFile.tsx +++ b/src/frontend/platform/src/pages/KnowledgePage/components/PreviewFile.tsx @@ -8,6 +8,7 @@ import DocxPreview from "./DocxFileViewer"; import { convertJsonData } from "./ParagraphEdit"; import { Partition } from "./PreviewResult"; import TxtFileViewer from "./TxtFileViewer"; +import { cn } from "@/utils"; export default function PreviewFile({ urlState, @@ -292,7 +293,7 @@ export default function PreviewFile({ if (['xlsx', 'xls', 'csv'].includes(file.suffix)) return null - return
{ + return
{ e.stopPropagation() }}>
diff --git a/src/frontend/platform/src/pages/KnowledgePage/components/PreviewResult.tsx b/src/frontend/platform/src/pages/KnowledgePage/components/PreviewResult.tsx index 26b0ba547..5efd08e4e 100644 --- a/src/frontend/platform/src/pages/KnowledgePage/components/PreviewResult.tsx +++ b/src/frontend/platform/src/pages/KnowledgePage/components/PreviewResult.tsx @@ -146,9 +146,19 @@ console.log(showPreview, previewCount, rules, step, applyEachCell, cellGeneralCo // 更新分段 const selectedBbox = useKnowledgeStore((state) => state.selectedBbox); const handleChunkChange = (chunkIndex, text) => { - const bbox = { chunk_bboxes: selectedBbox } + + + const existingBbox = chunks[chunkIndex]?.bbox ? JSON.parse(chunks[chunkIndex].bbox) : { chunk_bboxes: [] }; + const targetChunkBboxes = selectedBbox && selectedBbox.length > 0 + ? selectedBbox + : existingBbox.chunk_bboxes; + const bbox = { + chunk_bboxes: targetChunkBboxes + }; + console.log( bbox,existingBbox,98999898); + updatePreviewChunkApi({ - knowledge_id: Number(id), file_path: currentFile.filePath, chunk_index: chunkIndex, text, bbox: JSON.stringify(bbox) + knowledge_id: Number(id)||kId, file_path: currentFile.filePath, chunk_index: chunkIndex, text, bbox: JSON.stringify(bbox) }) setChunks(chunks => chunks.map(chunk => chunk.chunkIndex === chunkIndex ? { ...chunk, text } : chunk)) } @@ -163,7 +173,7 @@ console.log(showPreview, previewCount, rules, step, applyEachCell, cellGeneralCo setChunks={setChunks} partitions={partitions} />} -
+
{/* 下拉框 - 右上角 */} {(step === 3 || (step === 2 && showPreview)) && (
diff --git a/src/frontend/platform/src/pages/KnowledgePage/components/RuleFile.tsx b/src/frontend/platform/src/pages/KnowledgePage/components/RuleFile.tsx index f39bc4d8f..a9d8c1162 100644 --- a/src/frontend/platform/src/pages/KnowledgePage/components/RuleFile.tsx +++ b/src/frontend/platform/src/pages/KnowledgePage/components/RuleFile.tsx @@ -186,7 +186,7 @@ export default function RuleFile({ return (
-
+

{t('splitSettings')}