diff --git a/frontend/src/pages/DataAnnotation/Template/TemplateDetail.tsx b/frontend/src/pages/DataAnnotation/Template/TemplateDetail.tsx index 202aa6f..091eadf 100644 --- a/frontend/src/pages/DataAnnotation/Template/TemplateDetail.tsx +++ b/frontend/src/pages/DataAnnotation/Template/TemplateDetail.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { Modal, Descriptions, Tag, Space, Divider, Card, Typography } from "antd"; +import { Modal, Descriptions, Tag, Space, Divider, Card, Typography, Image, Empty } from "antd"; import type { AnnotationTemplate } from "../annotation.model"; const { Text, Paragraph } = Typography; @@ -81,6 +81,69 @@ const TemplateDetail: React.FC = ({ + {/* 示例数据预览 */} + + {template.configuration.exampleData && + Object.keys(template.configuration.exampleData).length > 0 ? ( + + {template.configuration.objects.map((obj, index) => { + const varName = obj.value?.replace(/^\$/, "") || obj.name; + const exampleValue = template.configuration.exampleData?.[varName]; + + if (!exampleValue) return null; + + return ( + + +
+ {obj.name} + + ({obj.type}) + +
+ {/* 根据类型渲染不同的预览 */} + {obj.type === "Image" ? ( + {`示例: + ) : obj.type === "Audio" ? ( +
+
+ ); + })} +
+ ) : ( + + )} +
+ {template.configuration.labels.map((label, index) => ( diff --git a/frontend/src/pages/DataAnnotation/annotation.model.ts b/frontend/src/pages/DataAnnotation/annotation.model.ts index e74859a..42b4e23 100644 --- a/frontend/src/pages/DataAnnotation/annotation.model.ts +++ b/frontend/src/pages/DataAnnotation/annotation.model.ts @@ -53,6 +53,12 @@ export interface TemplateConfiguration { labels: LabelDefinition[]; objects: ObjectDefinition[]; metadata?: Record; + /** + * 示例数据,用于模板预览 + * key: 变量名(不带$前缀,如 "image"、"text") + * value: 示例内容(URL 或文本) + */ + exampleData?: Record; } export interface AnnotationTemplate { diff --git a/frontend/src/pages/DataAnnotation/components/TemplateConfigurationForm.tsx b/frontend/src/pages/DataAnnotation/components/TemplateConfigurationForm.tsx index 90995ea..708039c 100644 --- a/frontend/src/pages/DataAnnotation/components/TemplateConfigurationForm.tsx +++ b/frontend/src/pages/DataAnnotation/components/TemplateConfigurationForm.tsx @@ -8,11 +8,15 @@ import { Divider, Card, Checkbox, + Typography, + Image, } from "antd"; import { PlusOutlined, MinusCircleOutlined } from "@ant-design/icons"; import TagSelector from "../Template/components/TagSelector"; const { Option } = Select; +const { TextArea } = Input; +const { Text } = Typography; interface TemplateConfigurationFormProps { form: any; @@ -27,6 +31,31 @@ const TemplateConfigurationForm: React.FC = ({ ); }; + /** 判断对象类型是否为文本类 */ + const isTextType = (type: string) => { + return ["Text", "HyperText", "Table", "List"].includes(type); + }; + + /** 判断对象类型是否为图片类 */ + const isImageType = (type: string) => { + return ["Image"].includes(type); + }; + + /** 获取示例数据输入提示 */ + const getExamplePlaceholder = (type: string) => { + const map: Record = { + Text: "输入示例文本内容...", + HyperText: "输入示例 HTML 内容...", + Image: "输入图片 URL,如 https://example.com/image.jpg", + Audio: "输入音频 URL,如 https://example.com/audio.mp3", + Video: "输入视频 URL,如 https://example.com/video.mp4", + Table: "输入示例表格数据(JSON 格式)...", + List: "输入示例列表数据(JSON 格式)...", + TimeSeries: "输入时间序列数据 URL...", + }; + return map[type] || "输入示例数据..."; + }; + return ( <> 数据对象 @@ -287,6 +316,78 @@ const TemplateConfigurationForm: React.FC = ({ )} + + 示例数据(可选) + + + 为数据对象提供示例数据,帮助用户在模板预览时直观了解标注效果 + + prev.objects !== curr.objects}> + {({ getFieldValue }) => { + const objects = getFieldValue("objects") || []; + if (objects.length === 0) { + return ( + 请先添加数据对象 + ); + } + return ( + + {objects.map((obj: any, index: number) => { + if (!obj?.name) return null; + const varName = obj.value?.replace(/^\$/, "") || obj.name; + const objType = obj.type || "Text"; + + return ( + + +
+ {obj.name} + + ({objType}) + +
+ + {isTextType(objType) ? ( +