From 719f54bf2e265faff0b504e5ba855b4524c13fb4 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Thu, 5 Feb 2026 23:22:49 +0800 Subject: [PATCH] =?UTF-8?q?feat(annotation):=20=E5=AE=8C=E5=96=84=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=89=88=E6=9C=AC=E7=AE=A1=E7=90=86=E5=92=8C=E6=A0=87?= =?UTF-8?q?=E6=B3=A8=E5=90=8C=E6=AD=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将 useNewVersionUsingPost 重命名为 applyNewVersionUsingPost - 添加 fileVersionCheckSeqRef 避免版本检查竞态条件 - 移除 checkingFileVersion 状态变量的渲染依赖 - 在文件版本信息中添加 annotationVersionUnknown 字段 - 修复前端文件版本比较显示的 JSX 语法 - 添加历史标注缺少版本信息的提示显示 - 配置 Alembic 异步数据库迁移环境支持 aiomysql - 添加文件版本未知状态的后端判断逻辑 - 实现标注清除时的段落注释清理功能 - 添加知识库同步钩子到版本更新流程 --- .../Annotate/LabelStudioTextEditor.tsx | 20 ++++-- .../pages/DataAnnotation/annotation.api.ts | 3 +- runtime/datamate-python/alembic/env.py | 58 ++++++++++++---- .../app/module/annotation/schema/editor.py | 5 ++ .../app/module/annotation/service/editor.py | 68 ++++++++++++------- 5 files changed, 109 insertions(+), 45 deletions(-) diff --git a/frontend/src/pages/DataAnnotation/Annotate/LabelStudioTextEditor.tsx b/frontend/src/pages/DataAnnotation/Annotate/LabelStudioTextEditor.tsx index 5f3192c..9fdc324 100644 --- a/frontend/src/pages/DataAnnotation/Annotate/LabelStudioTextEditor.tsx +++ b/frontend/src/pages/DataAnnotation/Annotate/LabelStudioTextEditor.tsx @@ -9,7 +9,7 @@ import { listEditorTasksUsingGet, upsertEditorAnnotationUsingPut, checkFileVersionUsingGet, - useNewVersionUsingPost, + applyNewVersionUsingPost, type FileVersionCheckResponse, } from "../annotation.api"; import { AnnotationResultStatus } from "../annotation.model"; @@ -232,6 +232,7 @@ export default function LabelStudioTextEditor() { const origin = useMemo(() => window.location.origin, []); const iframeRef = useRef(null); const initSeqRef = useRef(0); + const fileVersionCheckSeqRef = useRef(0); const expectedTaskIdRef = useRef(null); const prefetchSeqRef = useRef(0); const exportCheckRef = useRef<{ @@ -274,7 +275,7 @@ export default function LabelStudioTextEditor() { // 文件版本相关状态 const [fileVersionInfo, setFileVersionInfo] = useState(null); - const [checkingFileVersion, setCheckingFileVersion] = useState(false); + const [, setCheckingFileVersion] = useState(false); const [usingNewVersion, setUsingNewVersion] = useState(false); const focusIframe = useCallback(() => { @@ -558,9 +559,11 @@ export default function LabelStudioTextEditor() { const checkFileVersion = useCallback(async (fileId: string) => { if (!projectId || !fileId) return; + const seq = ++fileVersionCheckSeqRef.current; setCheckingFileVersion(true); try { const resp = (await checkFileVersionUsingGet(projectId, fileId)) as ApiResponse; + if (seq !== fileVersionCheckSeqRef.current) return; const data = resp?.data; if (data) { setFileVersionInfo(data); @@ -584,9 +587,9 @@ export default function LabelStudioTextEditor() { } catch (e) { console.error("检查文件版本失败", e); } finally { - setCheckingFileVersion(false); + if (seq === fileVersionCheckSeqRef.current) setCheckingFileVersion(false); } - }, [modal, message, projectId]); + }, [modal, projectId]); const handleUseNewVersion = useCallback(async () => { if (!selectedFileId) return; @@ -612,7 +615,7 @@ export default function LabelStudioTextEditor() { if (!projectId || !selectedFileId) return; setUsingNewVersion(true); try { - await useNewVersionUsingPost(projectId, selectedFileId); + await applyNewVersionUsingPost(projectId, selectedFileId); message.success("已使用新版本并清空标注"); setFileVersionInfo(null); await loadTasks({ mode: "reset" }); @@ -985,7 +988,7 @@ export default function LabelStudioTextEditor() { {fileVersionInfo?.hasNewVersion && (
- ⚠ 文件有新版本({fileVersionInfo.currentFileVersion} > {fileVersionInfo.annotationFileVersion}) + ⚠ 文件有新版本({fileVersionInfo.currentFileVersion}{" > "}{fileVersionInfo.annotationFileVersion})
)} + {fileVersionInfo?.annotationVersionUnknown && !fileVersionInfo?.hasNewVersion && ( + + 历史标注缺少文件版本信息,保存后将绑定当前版本({fileVersionInfo.currentFileVersion}) + + )}