You've already forked DataMate
feat(annotation): 添加数据类型过滤功能到标签配置树编辑器
- 引入 DataType 枚举类型定义 - 根据数据类型动态过滤对象标签选项 - 在模板表单中添加数据类型监听 - 改进错误处理逻辑以提高类型安全性 - 集成数据类型参数到配置树编辑器组件
This commit is contained in:
@@ -36,6 +36,7 @@ const TemplateForm: React.FC<TemplateFormProps> = ({
|
|||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [labelConfig, setLabelConfig] = useState("");
|
const [labelConfig, setLabelConfig] = useState("");
|
||||||
|
const selectedDataType = Form.useWatch("dataType", form);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible && template && mode === "edit") {
|
if (visible && template && mode === "edit") {
|
||||||
@@ -96,8 +97,12 @@ const TemplateForm: React.FC<TemplateFormProps> = ({
|
|||||||
} else {
|
} else {
|
||||||
message.error(response.message || `模板${mode === "create" ? "创建" : "更新"}失败`);
|
message.error(response.message || `模板${mode === "create" ? "创建" : "更新"}失败`);
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: unknown) {
|
||||||
if (error.errorFields) {
|
const hasErrorFields =
|
||||||
|
typeof error === "object" &&
|
||||||
|
error !== null &&
|
||||||
|
"errorFields" in error;
|
||||||
|
if (hasErrorFields) {
|
||||||
message.error("请填写所有必填字段");
|
message.error("请填写所有必填字段");
|
||||||
} else {
|
} else {
|
||||||
message.error(`模板${mode === "create" ? "创建" : "更新"}失败`);
|
message.error(`模板${mode === "create" ? "创建" : "更新"}失败`);
|
||||||
@@ -195,6 +200,7 @@ const TemplateForm: React.FC<TemplateFormProps> = ({
|
|||||||
value={labelConfig}
|
value={labelConfig}
|
||||||
onChange={setLabelConfig}
|
onChange={setLabelConfig}
|
||||||
height={420}
|
height={420}
|
||||||
|
dataType={selectedDataType}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import {
|
|||||||
getObjectDisplayName,
|
getObjectDisplayName,
|
||||||
type LabelStudioTagConfig,
|
type LabelStudioTagConfig,
|
||||||
} from "../annotation.tagconfig";
|
} from "../annotation.tagconfig";
|
||||||
|
import { DataType } from "../annotation.model";
|
||||||
|
|
||||||
const { Text, Title } = Typography;
|
const { Text, Title } = Typography;
|
||||||
|
|
||||||
@@ -44,10 +45,22 @@ interface TemplateConfigurationTreeEditorProps {
|
|||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
readOnlyStructure?: boolean;
|
readOnlyStructure?: boolean;
|
||||||
height?: number | string;
|
height?: number | string;
|
||||||
|
dataType?: DataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_ROOT_TAG = "View";
|
const DEFAULT_ROOT_TAG = "View";
|
||||||
const CHILD_TAGS = ["Label", "Choice", "Relation", "Item", "Path", "Channel"];
|
const CHILD_TAGS = ["Label", "Choice", "Relation", "Item", "Path", "Channel"];
|
||||||
|
const OBJECT_TAGS_BY_DATA_TYPE: Record<DataType, string[]> = {
|
||||||
|
[DataType.TEXT]: ["Text", "Paragraphs", "Markdown"],
|
||||||
|
[DataType.IMAGE]: ["Image", "Bitmask"],
|
||||||
|
[DataType.AUDIO]: ["Audio", "AudioPlus"],
|
||||||
|
[DataType.VIDEO]: ["Video"],
|
||||||
|
[DataType.PDF]: ["PDF"],
|
||||||
|
[DataType.TIMESERIES]: ["Timeseries", "TimeSeries", "Vector"],
|
||||||
|
[DataType.CHAT]: ["Chat"],
|
||||||
|
[DataType.HTML]: ["HyperText", "Markdown"],
|
||||||
|
[DataType.TABLE]: ["Table", "Vector"],
|
||||||
|
};
|
||||||
|
|
||||||
const createId = () =>
|
const createId = () =>
|
||||||
`node_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
`node_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
||||||
@@ -436,6 +449,7 @@ const TemplateConfigurationTreeEditor = ({
|
|||||||
readOnly = false,
|
readOnly = false,
|
||||||
readOnlyStructure = false,
|
readOnlyStructure = false,
|
||||||
height = 420,
|
height = 420,
|
||||||
|
dataType,
|
||||||
}: TemplateConfigurationTreeEditorProps) => {
|
}: TemplateConfigurationTreeEditorProps) => {
|
||||||
const { config } = useTagConfig(false);
|
const { config } = useTagConfig(false);
|
||||||
const [tree, setTree] = useState<XmlNode>(() => createEmptyTree());
|
const [tree, setTree] = useState<XmlNode>(() => createEmptyTree());
|
||||||
@@ -512,11 +526,17 @@ const TemplateConfigurationTreeEditor = ({
|
|||||||
|
|
||||||
const objectOptions = useMemo(() => {
|
const objectOptions = useMemo(() => {
|
||||||
if (!config?.objects) return [];
|
if (!config?.objects) return [];
|
||||||
return Object.keys(config.objects).map((tag) => ({
|
const options = Object.keys(config.objects).map((tag) => ({
|
||||||
value: tag,
|
value: tag,
|
||||||
label: getObjectDisplayName(tag),
|
label: getObjectDisplayName(tag),
|
||||||
}));
|
}));
|
||||||
}, [config]);
|
if (!dataType) return options;
|
||||||
|
const allowedTags = OBJECT_TAGS_BY_DATA_TYPE[dataType];
|
||||||
|
if (!allowedTags) return options;
|
||||||
|
const allowedSet = new Set(allowedTags);
|
||||||
|
const filtered = options.filter((option) => allowedSet.has(option.value));
|
||||||
|
return filtered.length > 0 ? filtered : options;
|
||||||
|
}, [config, dataType]);
|
||||||
|
|
||||||
const tagOptions = useMemo(() => {
|
const tagOptions = useMemo(() => {
|
||||||
const options = [] as {
|
const options = [] as {
|
||||||
|
|||||||
Reference in New Issue
Block a user