From e1c963928afb5a6c8762c2cec2459bad29cb14c3 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sat, 31 Jan 2026 16:14:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(annotation):=20=E6=B7=BB=E5=8A=A0=E6=A0=87?= =?UTF-8?q?=E6=B3=A8=E5=AF=B9=E8=B1=A1=E8=A7=A3=E6=9E=90=E5=92=8C=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 实现 isAnnotationObject 函数验证标注对象 - 添加 resolveSelectedAnnotation 函数解析选中标注 - 优化 exportSelectedAnnotation 函数的标注选择逻辑 - 添加未找到标注对象的错误处理 - 支持 results 字段到 result 字段的自动转换 - 提升标注数据导出的稳定性和准确性 --- frontend/public/lsf/lsf.html | 39 ++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/frontend/public/lsf/lsf.html b/frontend/public/lsf/lsf.html index d265b29..f0ac2f4 100644 --- a/frontend/public/lsf/lsf.html +++ b/frontend/public/lsf/lsf.html @@ -169,6 +169,33 @@ } } + function isAnnotationObject(value) { + if (!value || typeof value !== "object") return false; + return typeof value.serializeAnnotation === "function" || typeof value.serialize === "function"; + } + + function resolveSelectedAnnotation(store) { + if (!store) return null; + const annotations = Array.isArray(store.annotations) ? store.annotations : []; + if (isAnnotationObject(store.selectedAnnotation)) { + return store.selectedAnnotation; + } + if (isAnnotationObject(store.selected)) { + return store.selected; + } + const selectedId = store.selected; + if (selectedId !== undefined && selectedId !== null && annotations.length) { + const matched = annotations.find((ann) => ann && String(ann.id) === String(selectedId)); + if (isAnnotationObject(matched)) { + return matched; + } + } + if (annotations.length && isAnnotationObject(annotations[0])) { + return annotations[0]; + } + return null; + } + function exportSelectedAnnotation() { if (!lsInstance) { throw new Error("LabelStudio 未初始化"); @@ -179,10 +206,10 @@ throw new Error("无法访问 annotationStore"); } - const selected = - store.selected || - store.selectedAnnotation || - (Array.isArray(store.annotations) && store.annotations.length ? store.annotations[0] : null); + const selected = resolveSelectedAnnotation(store); + if (!selected) { + throw new Error("未找到可导出的标注对象"); + } let serialized = null; if (selected && typeof selected.serializeAnnotation === "function") { @@ -197,6 +224,10 @@ ? { id: selected?.id || serialized.id || "draft", ...serialized } : { id: selected?.id || "draft", result: (selected && selected.result) || [] }; + if (!Array.isArray(annotationPayload.result) && Array.isArray(annotationPayload.results)) { + annotationPayload.result = annotationPayload.results; + } + // 最小化对齐 Label Studio Server 的字段(DataMate 侧会原样存储) const taskId = typeof currentTask?.id === "number" ? currentTask.id : Number(currentTask?.id) || null; const fileId = currentTask?.data?.file_id || currentTask?.data?.fileId || null;