You've already forked DataMate
feat(annotation): 添加标注模板配置功能
- 在schema中新增choice和show_inline字段支持选择模式配置 - 为编辑器服务添加空标注创建逻辑避免前端异常 - 实现标签类型的标准化处理和大小写兼容 - 支持Choices标签的单选/多选和行内显示配置 - 优化前端界面滚动条显示控制样式
This commit is contained in:
@@ -9,9 +9,11 @@
|
|||||||
body {
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
#label-studio {
|
#label-studio {
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ class LabelDefinition(BaseModel):
|
|||||||
options: Optional[List[str]] = Field(None, description="选项列表(用于choices类型)")
|
options: Optional[List[str]] = Field(None, description="选项列表(用于choices类型)")
|
||||||
labels: Optional[List[str]] = Field(None, description="标签列表(用于rectanglelabels等类型)")
|
labels: Optional[List[str]] = Field(None, description="标签列表(用于rectanglelabels等类型)")
|
||||||
required: bool = Field(False, description="是否必填")
|
required: bool = Field(False, description="是否必填")
|
||||||
|
choice: Optional[str] = Field(None, description="Choices 选择模式: single/multiple")
|
||||||
|
show_inline: Optional[bool] = Field(None, alias="showInline", description="Choices 是否行内显示")
|
||||||
description: Optional[str] = Field(None, description="标签描述")
|
description: Optional[str] = Field(None, description="标签描述")
|
||||||
|
|
||||||
model_config = ConfigDict(populate_by_name=True)
|
model_config = ConfigDict(populate_by_name=True)
|
||||||
|
|||||||
@@ -251,6 +251,18 @@ class AnnotationEditorService:
|
|||||||
if not isinstance(stored.get("id"), int):
|
if not isinstance(stored.get("id"), int):
|
||||||
stored["id"] = self._make_ls_annotation_id(project_id, file_id)
|
stored["id"] = self._make_ls_annotation_id(project_id, file_id)
|
||||||
task["annotations"] = [stored]
|
task["annotations"] = [stored]
|
||||||
|
else:
|
||||||
|
# 提供一个空 annotation,避免前端在没有选中 annotation 时无法产生 result
|
||||||
|
empty_ann_id = self._make_ls_annotation_id(project_id, file_id)
|
||||||
|
task["annotations"] = [
|
||||||
|
{
|
||||||
|
"id": empty_ann_id,
|
||||||
|
"task": ls_task_id,
|
||||||
|
"result": [],
|
||||||
|
"created_at": datetime.utcnow().isoformat() + "Z",
|
||||||
|
"updated_at": datetime.utcnow().isoformat() + "Z",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
return EditorTaskResponse(
|
return EditorTaskResponse(
|
||||||
task=task,
|
task=task,
|
||||||
|
|||||||
@@ -35,8 +35,20 @@ class AnnotationTemplateService:
|
|||||||
Label Studio XML字符串
|
Label Studio XML字符串
|
||||||
"""
|
"""
|
||||||
tag_config = LabelStudioTagConfig()
|
tag_config = LabelStudioTagConfig()
|
||||||
|
control_types = tag_config.get_control_types()
|
||||||
xml_parts = ['<View>']
|
xml_parts = ['<View>']
|
||||||
|
|
||||||
|
def normalize_control_type(raw: Optional[str]) -> str:
|
||||||
|
if not raw:
|
||||||
|
return "Choices"
|
||||||
|
if raw in control_types:
|
||||||
|
return raw
|
||||||
|
raw_lower = raw.lower()
|
||||||
|
for ct in control_types:
|
||||||
|
if ct.lower() == raw_lower:
|
||||||
|
return ct
|
||||||
|
return raw
|
||||||
|
|
||||||
# 生成对象定义
|
# 生成对象定义
|
||||||
for obj in config.objects:
|
for obj in config.objects:
|
||||||
obj_attrs = [
|
obj_attrs = [
|
||||||
@@ -47,16 +59,17 @@ class AnnotationTemplateService:
|
|||||||
|
|
||||||
# 生成标签定义
|
# 生成标签定义
|
||||||
for label in config.labels:
|
for label in config.labels:
|
||||||
label_attrs = [
|
label_attrs = [f'name="{label.from_name}"', f'toName="{label.to_name}"']
|
||||||
f'name="{label.from_name}"',
|
|
||||||
f'toName="{label.to_name}"'
|
|
||||||
]
|
|
||||||
|
|
||||||
# 添加可选属性
|
# 添加可选属性
|
||||||
if label.required:
|
if label.required:
|
||||||
label_attrs.append('required="true"')
|
label_attrs.append('required="true"')
|
||||||
|
|
||||||
tag_type = label.type.capitalize() if label.type else "Choices"
|
tag_type = normalize_control_type(label.type)
|
||||||
|
if tag_type == "Choices" and label.choice:
|
||||||
|
label_attrs.append(f'choice="{label.choice}"')
|
||||||
|
if tag_type == "Choices" and label.show_inline is not None:
|
||||||
|
label_attrs.append(f'showInline="{"true" if label.show_inline else "false"}"')
|
||||||
|
|
||||||
# 检查是否需要子元素
|
# 检查是否需要子元素
|
||||||
if label.options or label.labels:
|
if label.options or label.labels:
|
||||||
|
|||||||
Reference in New Issue
Block a user