feat(annotation): 添加标注对象解析和导出功能

- 实现 isAnnotationObject 函数验证标注对象
- 添加 resolveSelectedAnnotation 函数解析选中标注
- 优化 exportSelectedAnnotation 函数的标注选择逻辑
- 添加未找到标注对象的错误处理
- 支持 results 字段到 result 字段的自动转换
- 提升标注数据导出的稳定性和准确性
This commit is contained in:
2026-01-31 16:14:12 +08:00
parent 33cf65c9f8
commit e1c963928a

View File

@@ -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() { function exportSelectedAnnotation() {
if (!lsInstance) { if (!lsInstance) {
throw new Error("LabelStudio 未初始化"); throw new Error("LabelStudio 未初始化");
@@ -179,10 +206,10 @@
throw new Error("无法访问 annotationStore"); throw new Error("无法访问 annotationStore");
} }
const selected = const selected = resolveSelectedAnnotation(store);
store.selected || if (!selected) {
store.selectedAnnotation || throw new Error("未找到可导出的标注对象");
(Array.isArray(store.annotations) && store.annotations.length ? store.annotations[0] : null); }
let serialized = null; let serialized = null;
if (selected && typeof selected.serializeAnnotation === "function") { if (selected && typeof selected.serializeAnnotation === "function") {
@@ -197,6 +224,10 @@
? { id: selected?.id || serialized.id || "draft", ...serialized } ? { id: selected?.id || serialized.id || "draft", ...serialized }
: { id: selected?.id || "draft", result: (selected && selected.result) || [] }; : { 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 侧会原样存储) // 最小化对齐 Label Studio Server 的字段(DataMate 侧会原样存储)
const taskId = typeof currentTask?.id === "number" ? currentTask.id : Number(currentTask?.id) || null; const taskId = typeof currentTask?.id === "number" ? currentTask.id : Number(currentTask?.id) || null;
const fileId = currentTask?.data?.file_id || currentTask?.data?.fileId || null; const fileId = currentTask?.data?.file_id || currentTask?.data?.fileId || null;